Best way to remove items from a collection

前端 未结 15 2063
天命终不由人
天命终不由人 2020-12-08 05:47

What is the best way to approach removing items from a collection in C#, once the item is known, but not it\'s index. This is one way to do it, but it seems inelegant at be

15条回答
  •  北荒
    北荒 (楼主)
    2020-12-08 06:40

    If you have got a List, then List.RemoveAll is your best bet. There can't be anything more efficient. Internally it does the array moving in one shot, not to mention it is O(N).

    If all you got is an IList or an ICollection you got roughly these three options:

        public static void RemoveAll(this IList ilist, Predicate predicate) // O(N^2)
        {
            for (var index = ilist.Count - 1; index >= 0; index--)
            {
                var item = ilist[index];
                if (predicate(item))
                {
                    ilist.RemoveAt(index);
                }
            }
        }
    

    or

        public static void RemoveAll(this ICollection icollection, Predicate predicate) // O(N)
        {
            var nonMatchingItems = new List();
    
            // Move all the items that do not match to another collection.
            foreach (var item in icollection) 
            {
                if (!predicate(item))
                {
                    nonMatchingItems.Add(item);
                }
            }
    
            // Clear the collection and then copy back the non-matched items.
            icollection.Clear();
            foreach (var item in nonMatchingItems)
            {
                icollection.Add(item);
            }
        }
    

    or

        public static void RemoveAll(this ICollection icollection, Func predicate) // O(N^2)
        {
            foreach (var item in icollection.Where(predicate).ToList())
            {
                icollection.Remove(item);
            }
        }
    

    Go for either 1 or 2.

    1 is lighter on memory and faster if you have less deletes to perform (i.e. predicate is false most of the times).

    2 is faster if you have more deletes to perform.

    3 is the cleanest code but performs poorly IMO. Again all that depends on input data.

    For some benchmarking details see https://github.com/dotnet/BenchmarkDotNet/issues/1505

提交回复
热议问题