Best way to remove items from a collection

前端 未结 15 2031
天命终不由人
天命终不由人 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:45

    @smaclell asked why reverse iteration was more efficient in in a comment to @sambo99.

    Sometimes it's more efficient. Consider you have a list of people, and you want to remove or filter all customers with a credit rating < 1000;

    We have the following data

    "Bob" 999
    "Mary" 999
    "Ted" 1000
    

    If we were to iterate forward, we'd soon get into trouble

    for( int idx = 0; idx < list.Count ; idx++ )
    {
        if( list[idx].Rating < 1000 )
        {
            list.RemoveAt(idx); // whoops!
        }
    }
    

    At idx = 0 we remove Bob, which then shifts all remaining elements left. The next time through the loop idx = 1, but list[1] is now Ted instead of Mary. We end up skipping Mary by mistake. We could use a while loop, and we could introduce more variables.

    Or, we just reverse iterate:

    for (int idx = list.Count-1; idx >= 0; idx--)
    {
        if (list[idx].Rating < 1000)
        {
            list.RemoveAt(idx);
        }
    }
    

    All the indexes to the left of the removed item stay the same, so you don't skip any items.

    The same principle applies if you're given a list of indexes to remove from an array. In order to keep things straight you need to sort the list and then remove the items from highest index to lowest.

    Now you can just use Linq and declare what you're doing in a straightforward manner.

    list.RemoveAll(o => o.Rating < 1000);
    

    For this case of removing a single item, it's no more efficient iterating forwards or backwards. You could also use Linq for this.

    int removeIndex = list.FindIndex(o => o.Name == "Ted");
    if( removeIndex != -1 )
    {
        list.RemoveAt(removeIndex);
    }
    

提交回复
热议问题