【问题标题】:Deleting item from a List<Type>从 List<Type> 中删除项目
【发布时间】:2011-11-19 15:42:42
【问题描述】:

这就是我从List 中删除项目的方法。这是正确的方法吗?有没有更清洁/更快的方法来实现这一点。

List<ItemClass> itemsToErase = new List<ItemClass>();
foreach(ItemClass itm in DS)
{
       if(itm.ToBeRemoved)
            itemsToErase .Add(itm);
}
foreach(ItemClass eraseItem in itemsToErase)
{
      DS.Remove(eraseItem );
}      

编辑:DS 的类型为 List&lt;ItemClass&gt;

编辑:还有一个疑问。如果 DS 是LinkedList&lt;ItemClass&gt; 怎么办?没有RemoveAll()

【问题讨论】:

    标签: c#


    【解决方案1】:

    List.RemoveAll() 接受一个委托,您可以在其中添加比较函数。

    例如:

    List<ItemClass> itemsToErase = new List<ItemClass>();
    itemsToErase.RemoveAll( itm => itm.ToBeRemoved );
    

    【讨论】:

      【解决方案2】:

      你可以使用the RemoveAll() method:

      DS.RemoveAll(x => x.ToBeRemoved);
      

      这是一个 O(n) 操作,你的代码是 O(n^2)。

      【讨论】:

        【解决方案3】:

        这种方法避免了原始List中的大量副本,但内存消耗更大。

        List<ItemClass> newList = new List<ItemClass>(originalList.Count);
        
        foreach(var item in originalList) {
            if (!item.ToBeRemoved) 
                newList.Add(item);
        }
        
        originalList = newList;
        

        【讨论】:

        • +1。这可能是最快的方法。另一种快速但更复杂的方法是,使用列表索引器重新排列保留的项目,最后使用 RemoveRange 方法截断列表。
        【解决方案4】:

        不是真的,不管你怎么做,逻辑都是一样的。您不能同时迭代和修改集合。它看起来使用 LINQ 更干净:

        var list = new List<int> { 1, 2, 3, 4, 5 };
        var except = new List<int> { 3, 4 };
        var result = list.Except(except);
        

        希望这会有所帮助。

        编辑:即使list.RemoveAll(...) 也必须在内部维护两个列表才能做到这一点。

        edit2:其实 svick 是对的;看了下实现,RemoveAll 是最快的。

        【讨论】:

        • 有趣。 LINQ 更干净,但不是更快?
        • 除了result 不再是List。如果你想这样,你必须打电话给ToList(),如果列表很大,这可能是复制太多了。
        • RemoveAll() 不必维护两个列表。这一切都在一个列表中完成。
        【解决方案5】:

        使用这个方法

         DS.RemoveAll(x => x.ToBeRemoved); 
        

        【讨论】:

          【解决方案6】:

          您的代码是该问题的常见解决方案并且很好。特别是如果只有几个项目要删除。
          正如其他人建议的那样,您还可以创建一个包含要保留的项目的新列表,然后丢弃旧列表。如果要删除大多数项目并且只保留一小部分,这会更好。 在选择这两种方法中的任何一种时,请记住它们都需要分配一个新的列表对象。这种额外的内存分配可能不是问题,但也可能是,这取决于代码的其余部分在做什么。
          正如其他人所提到的,还有 RemoveAll 方法。这就是我会使用的,它整洁、清晰、高效,就像使用列表的任何东西一样。
          最后一个选项是使用索引来循环遍历集合。例如。
          (对不起 VB,我比 C# 更频繁地使用它,并且不想因为语法错误而混淆)

          Dim i as Integer
          Do While i<DS.Count
          If DS.Item(i).ToBeRemoved Then
          DS.RemoveAt(i)
          Else
          i+=1
          End If
          Loop
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-07-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-13
            • 1970-01-01
            相关资源
            最近更新 更多