J Andrews

In this code, I get a SystemInvalidOperation execution and I know why.

List<int> list = new List<int>();

for (int i = 1; i < 10; i++)
{
list.Add(i);
}

foreach (int i in list)
{
list.Remove(i);
}

I replaced the foreach with for:


List<int> list = new List<int>();

for (int i = 1; i < 10; i++)
{
list.Add(i);
}

for (int i = 0; i < list.Count; i++)
{
int remove = listIdea;
list.Remove(remove);
}

After the loop exits, I still have 4 items in the list.


Re: Visual C# Language Removing items in a list while iterating through it

J Andrews

In this code, I get a SystemInvalidOperation execution and I know why.

List<int> list = new List<int>();

for (int i = 1; i < 10; i++)
{
list.Add(i);
}

foreach (int i in list)
{
list.Remove(i);
}

I replaced the foreach with for:


List<int> list = new List<int>();

for (int i = 1; i < 10; i++)
{
list.Add(i);
}

for (int i = 0; i < list.Count; i++)
{
int remove = listIdea;
list.Remove(remove);
}

After the loop exits, I still have 4 items in the list.

How do I delete a few items in the list while iterating through it

http://generally.wordpress.com/2007/10/24/removing-items-in-a-list-while-iterating-through-it/




Re: Visual C# Language Removing items in a list while iterating through it

Manju Sandhu

Hi,

List<int> list = new List<int>();

for (int i = 1; i < 10; i++)

{

list.Add(i);

}

for (int i = 0; i < list.Count; i++)

{

int remove = listIdea;

list.Remove(remove);

i--; //add this line

}

or do this

int Count = list.Count;

for (int i = 0; i < Count; i++)

{

int remove = listIdea;

list.Remove(remove);

}

Regards,

Manju sandhu





Re: Visual C# Language Removing items in a list while iterating through it

Philip Johnson

in your for loop, each time it iterates through, it reevaluates the list.count value. Instead of having it as:

for (int i = 0; i < list.Count; i++)

change it to

int iCount = list.Count;

for (int i = 0; i < iCount ; i++)

so that list.count doesn't get changed each time you do a list.remove





Re: Visual C# Language Removing items in a list while iterating through it

TaylorMichaelL

Yes, as you know the collection can't change while enumerating it without getting that exception. The for loop is the correct alternative. Unfortunately you have an emoticon in your code so I can't tell what your looping index is. If it isn't 0 then your code will fail with an exception so I'll assume so. Let's walk through a smaller example:

list[0] = 1;

list[1] = 2;

list[2] = 3;

list[3] = 4;

for (int i = 0; i < list.Count; ++i)
{

list.Remove(listIdea);
};

Initial = { 1, 2, 3, 4 }, i = 0, list.Count = 4

First Pass = { 2, 3, 4 }, i = 1, list.Count = 3

Second Pass = { 3, 4 }, i = 2, list.Count = 2

See the problem As you drop elements from the list, Count drops but i goes up. When you get about half way they'll meet. The solution is to either cache the count up front before any changes or to use a while loop:

int count = list.Count;

for (int i = 0; i < count; ++i)

{

};

while (list.Count > 0)
{
};

Also, just in case you didn't know, you can use Clear to empty out a collection or RemoveAll to conditionally clear the list.

Michael Taylor - 10/24/07

http://p3net.mvps.org





Re: Visual C# Language Removing items in a list while iterating through it

jgalley

This also would work:

Code Block

List<int> list = new List<int>();

for (int i = 1; i < 10; i++)
{
list.Add(i);
}

for (int i = list.Count-1; i >=0; i--)
{
/// **********************
/// Choose one
/// **********************
/// Remove positionally:
// list.RemoveAt(i);
/// **********************
/// Remove by value
// list.Remove(i);
/// **********************

list.RemoveAt(i);

}





Re: Visual C# Language Removing items in a list while iterating through it

J Andrews

Michael, sorry for the emoticon. [ i ] is being displayed as an emoticon, which is visible in your post also.

I understand the count decreasing and the index increasing portion. This is one of the problems, though. Another problem is this, which is clearly visible in your example:

Initial = { 1, 2, 3, 4 }, i = 0, list.Count = 4

First Pass = { 2, 3, 4 }, i = 1, list.Count = 3

Second Pass = { 3, 4 }, i = 2, list.Count = 2


In the first pass, i = 1, and hence the element removed is 3, not 2. In the second pass, no element is removed.



So, we have two problems.

1. index overtaking the count

2. list being reshuffled


Your solution for the first problem:

nt count = list.Count;

for (int i = 0; i < count; ++i)

{

list.Remove(i);

};

This will throw an exception at list.Remove(i) as soon as index exceeds the count.

And we haven't found a solution for the second problem.







Re: Visual C# Language Removing items in a list while iterating through it

J Andrews

Oh yeah, one solution for this could be:

int count = list.Count;

for(int i = 0; i < count; i++)
{
int elementToRemove = list.Find(<Predicate to find the element>);

list.Remove(elementToRemove);
}


But, performance is a big issue here.




Re: Visual C# Language Removing items in a list while iterating through it

Manju Sandhu

Hi,

Use this it will solve your problem

Either this

for (int i = 0; i < list.Count; i++)

{

int remove = list;

list.Remove(remove);

i--; //add this line

}

OR

int Count = list.Count

for (int i = 0; i < Count; i++)

{

int remove = list[0];

list.Remove(remove);

}

Regards,

Manju Sandhu





Re: Visual C# Language Removing items in a list while iterating through it

J Andrews

Manju Sandhu wrote:

for (int i = 0; i < list.Count; i++)

{

int remove = list;

list.Remove(remove);

i--; //add this line

}


int Count = list.Count

for (int i = 0; i < Count; i++)

{

int remove = list[0];

list.Remove(remove);

}



You are assuming I want to delete all the elements in the list. If I wanted to delete all elements, I would use list.Clear(), why do I need a loop at all

The problem arises when I want to delete the third, eighth and elevent element Or let's say I want to write a method

void DeleteElements(List<int> list, int[] indicesToDelete)
{
// This method removes the elements at the given indices from the list.
}

Now, I need to implement this function.






Re: Visual C# Language Removing items in a list while iterating through it

Manju Sandhu

Hi,

//Considered that indeces to delete are in ascending order

void DeleteElements(List<int> list, int[] indicesToDelete)
{

for(int j=0;j<indicesToDelete.Length;j++)
{

int remove = list[indicesToDelete[j]-j];

list.Remove(remove);

}

}

Regards,

Manju Sandhu





Re: Visual C# Language Removing items in a list while iterating through it

J Andrews

Thanks Manju, that's a neat solution.




Re: Visual C# Language Removing items in a list while iterating through it

Zamial

Hmm I to have had this problem in the past

I have usually created a copy of the element i'm iterating through and I perform the remove functions on the copy.

So lets for aguments sake say it is a simple List<string>

you can copy the List to another list.

then foreach string s in the first list

{

decide if it needs removing and if it does remove it from your copy.

}

Once finished your copy is the new list and you can dispose the old one.

Then you never need worry about indexes and counts





Re: Visual C# Language Removing items in a list while iterating through it

J Andrews

True, this is the solution I came up with before posting here. But, I prefer solution suggested here.






Re: Visual C# Language Removing items in a list while iterating through it

jgalley

Why not use a for loop to iterate the list backwards like I did in my example You can then remove items either by value or by position while iterating.