Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to iterate over a list and remove items from it? [closed]

Tags:

c#

iteration

list

I need to iterate over a List<myObject> and remove items that answer a certain condition.

I saw this answer (https://stackoverflow.com/a/1582317/5077434):

Iterate your list in reverse with a for loop:

for (int i = safePendingList.Count - 1; i >= 0; i--)
{
    // some code
    // safePendingList.RemoveAt(i);
}

Example:

var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
    if (list[i] > 5)
      list.RemoveAt(i);
}
list.ForEach(i => Console.WriteLine(i));

But I understood that for is less efficient than foreach,

So I thought of using the later as follows:

foreach (var item in myList.ToList())
{
    // if certain condition applies:
    myList.Remove(item)
}

Is one method better than the other?

EDIT:

I don't want to use RemoveAll(...), as there is a large amount of code inside the loop, prior to the condition.

like image 835
Aviran Katz Avatar asked Apr 18 '16 09:04

Aviran Katz


2 Answers

Willy-nilly you have to loop over the list, and the for loop is the most efficient one:

  for (int i = safePendingList.Count - 1; i >= 0; --i) 
    if (condition)
      safePendingList.RemoveAt(i);

If you want to remove in range (not in the entire list), just modify for loop:

  // No Enumarable.Range(1, 10) - put them into "for"
  for (int i = Math.Min(11, safePendingList.Count - 1); i >= 1; --i)
    if (condition)
      safePendingList.RemoveAt(i); 

Or if you have to remove items in forward looping:

  for (int i = 0; i < safePendingList.Count;) // notice ++i abscence
    if (condition)
      safePendingList.RemoveAt(i);
    else
      i += 1; // ++i should be here

On the contrary safePendingList.ToList() creates a copy of initial safePendingList and this means memory and CPU overhead:

  // safePendingList.ToList() - CPU and Memory overhead (copying)
  foreach (var item in safePendingList.ToList()) {
    if (condition)
      myList.Remove(item); // Overhead: searching
  }

However, the most reasonable plan in many cases is just to let .Net work for you:

  safePendingList.RemoveAll(item => condition);
like image 153
Dmitry Bychenko Avatar answered Oct 06 '22 01:10

Dmitry Bychenko


to remove items with a certain condition you can use

list.RemoveAll(item => item > 5);

instead of

var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
    if (list[i] > 5)
        list.RemoveAt(i);
}
like image 39
fubo Avatar answered Oct 05 '22 23:10

fubo