How to remove elements from a generic list while iterating over it?

前端 未结 27 2108
忘了有多久
忘了有多久 2020-11-21 22:48

I am looking for a better pattern for working with a list of elements which each need processed and then depending on the outcome are removed from

相关标签:
27条回答
  • 2020-11-21 23:12

    A simple and straightforward solution:

    Use a standard for-loop running backwards on your collection and RemoveAt(i) to remove elements.

    0 讨论(0)
  • 2020-11-21 23:12

    In C# one easy way is to mark the ones you wish to delete then create a new list to iterate over...

    foreach(var item in list.ToList()){if(item.Delete) list.Remove(item);}  
    

    or even simpler use linq....

    list.RemoveAll(p=>p.Delete);
    

    but it is worth considering if other tasks or threads will have access to the same list at the same time you are busy removing, and maybe use a ConcurrentList instead.

    0 讨论(0)
  • 2020-11-21 23:13
    List<T> TheList = new List<T>();
    
    TheList.FindAll(element => element.Satisfies(Condition)).ForEach(element => TheList.Remove(element));
    
    0 讨论(0)
  • 2020-11-21 23:14

    As any remove is taken on a condition you can use

    list.RemoveAll(item => item.Value == someValue);
    
    0 讨论(0)
  • 2020-11-21 23:14

    Just wanted to add my 2 cents to this in case this helps anyone, I had a similar problem but needed to remove multiple elements from an array list while it was being iterated over. the highest upvoted answer did it for me for the most part until I ran into errors and realized that the index was greater than the size of the array list in some instances because multiple elements were being removed but the index of the loop didn't keep track of that. I fixed this with a simple check:

    ArrayList place_holder = new ArrayList();
    place_holder.Add("1");
    place_holder.Add("2");
    place_holder.Add("3");
    place_holder.Add("4");
    
    for(int i = place_holder.Count-1; i>= 0; i--){
        if(i>= place_holder.Count){
            i = place_holder.Count-1; 
        }
    
    // some method that removes multiple elements here
    }
    
    0 讨论(0)
  • 2020-11-21 23:15

    If the function that determines which items to delete has no side effects and doesn't mutate the item (it's a pure function), a simple and efficient (linear time) solution is:

    list.RemoveAll(condition);
    

    If there are side effects, I'd use something like:

    var toRemove = new HashSet<T>();
    foreach(var item in items)
    {
         ...
         if(condition)
              toRemove.Add(item);
    }
    items.RemoveAll(toRemove.Contains);
    

    This is still linear time, assuming the hash is good. But it has an increased memory use due to the hashset.

    Finally if your list is only an IList<T> instead of a List<T> I suggest my answer to How can I do this special foreach iterator?. This will have linear runtime given typical implementations of IList<T>, compared with quadratic runtime of many other answers.

    0 讨论(0)
提交回复
热议问题