【问题标题】:Removing element from list with predicate使用谓词从列表中删除元素
【发布时间】:2012-02-19 17:18:46
【问题描述】:

我有一个来自 .NET 集合库的列表,我想删除一个元素。可悲的是,我无法通过直接与另一个对象进行比较来找到它。

我担心使用FindIndexRemoveAt会导致列表的多次遍历。

我不知道如何使用枚举器来删除元素,否则可能会起作用。

RemoveAll 做我需要的,但在找到一个元素后不会停止。

想法?

【问题讨论】:

  • 你能展示一些示例代码吗?
  • 问题标记为linked-list,但描述建议List<T>。是哪个?
  • 我以为List是一种链表?不是吗?
  • @Steinbitglis: List<T> 不是链表;这是dynamic array
  • @Steinbitglis:不,不是。它是由数组支持的。

标签: c# list collections linked-list


【解决方案1】:

如果有人需要同样的东西,但IList<T> (受 Strillo 回答的启发,但效率更高)

public bool Remove(this IList<T> list, Predicate<T> predicate)
{
    for(int i = 0; i < list.Count; i++)
    {
        if(predicate(list[i]))
        {
            list.RemoveAt(i);
            return true;
        }                   
    }   

    return false;
}

【讨论】:

    【解决方案2】:

    编辑:现在 OP 已更改为使用 LinkedList&lt;T&gt;,很容易给出一个只迭代到它必须的答案:

    public static void RemoveFirst<T>(LinkedList<T> list, Predicate<T> predicate)
    {
        var node = list.First;
        while (node != null)
        {
            if (predicate(node.Value))
            {
                list.Remove(node);
                return;
            }
            node = node.Next;
        }
    }
    

    【讨论】:

    • 我只想删除一个元素。
    • @Steinbitglis:会有多个值匹配谓词吗?您使用的是哪种列表?
    • @Steinbitglis:编辑显示如何使用副作用来使用RemoveAll
    • 这是我最终要寻找的解决方案,因此无论是否应得,我都将其标记为已接受的答案。
    • 如果它是对您帮助最大的答案,那么它绝对是当之无愧的。这就是“接受”的意思。
    【解决方案3】:

    List&lt;T&gt; 有一个接受谓词的FindIndex 方法

    int index = words.FindIndex(s => s.StartsWith("x"));
    words.RemoveAt(index);
    

    删除以“x”开头的第一个单词。在此示例中,words 假定为 List&lt;string&gt;

    【讨论】:

    • 如果 list 有一个恒定时间的索引查找,我认为这样就可以了。我担心 RemoveAt 也会遍历列表。
    • @Steinbitglis:这是一个 O(n) 操作,因为它必须复制所有内容。你真的想要一个链表吗?
    • 嗯,我有很少的元素,不断来来去去。我认为至少哈希表会很愚蠢。除了这个我想不通的看似微不足道的优化之外,我没有看到链表有任何问题。
    • 我切换到 LinkedList,希望能得到类似 Deque 的操作,我主要检查 1 或 2 个元素。
    • @Steinbitglis:如果你想要 LinkedList,我会取消删除我的答案,因为它已经包含了适合你的解决方案......
    【解决方案4】:

    如果您只想删除与谓词匹配的第一个元素,您可以使用以下(示例):

    List<int> list = new List<int>();
    list.Remove(list.FirstOrDefault(x => x = 10));
    

    (x =&gt; x = 10) 显然是匹配对象的谓词。

    【讨论】:

    • 这要求列表被枚举两次。一次找到匹配的项目。曾经在Remove 中再次找到此项目。
    • 没错,使用 RemoveAt 效率更高。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多