Suppose that I have the following code snippet:
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
}
}
The following code throws exception.
My question is what is the best way to avoid this exception and开发者_运维问答 to remove the element while looping?
If you need to remove elements then you must iterate backwards so you can remove elements from the end of the list:
var data=new List<string>(){"One","Two","Three"};
for(int i=data.Count - 1; i > -1; i--)
{
if(data[i]=="One")
{
data.RemoveAt(i);
}
}
However, there are more efficient ways to do this with LINQ (as indicated by the other answers).
You can use List<T>.RemoveAll
to handle this:
data.RemoveAll(elem => elem == "One");
You can also use a forward moving loop like:
var data = new List<string>() { "One", "Two", "Three", "One", "One", "Four" };
for (int i = 0; i < data.Count; i++)
{
if (data[i] == "One")
{
data.RemoveAt(i--);
}
}
This line data.RemoveAt(i--);
is stopping the effect of increment in the iteration variable at the end of the loop, in case of item being removed from the list.
It will remove the item from index at the current iteration value and then after removing the item, the iterator would be set to one less value than the current one. At the end of loop, the increment in loop body will move it to next valid index.
Here is a working dotfiddle
(Please note, that I personally use reverse loop for situation like these because IMO, they are easier to understand, this answer here is just for displaying another way of achieving it).
I happen to come across a simple solution for this using foreach
and .ToArray()
var data=new List<string>(){"One","Two","Three"};
foreach ( var d in data.ToArray()){
if(d =="One"){
data.Remove(d);
}
}
You could try ChrisF's reverse iteration method to remove your item.
You could also simply:
List.Remove("One");
Or:
List.RemoveAll(i => i == "One"); // removes all instances
And be done with it. There's really no point in iterating over the collection to remove a single item.
Why don't you just simply decrement the iterator variable?
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
i--; // <<<<<<<<<<<
}
}
Here is a dirty trick and I wonder what the critique of it will be?
var data=new List<string>(){"One","Two","Three"};
foreach (string itm in (data.ToArray()))
{
if string.Compare(name, "one", true) == 0) data.Remove(name);
}
var data=new List<string>(){"One","Two","Three"};
for(int i=0; i<data.Count; ){
if(data[i]=="One") data.RemoveAt(i);
else ++i;
}
The general solution below makes a copy of the list and handles the negative index:
foreach (void item_loopVariable in MyList.ToList) {
item = item_loopVariable;
}
var data = new List<string>() { "One", "Two", "Three" };
data.RemoveAll(p=>p=="One");
You can use Stack class
Stack<string> myStack = new Stack<string>();
foreach (var item in Enumerable.Range(1,1001))
myStack.Push("Str " + item.ToString());
while (myStack.Any())
Console.WriteLine("Now {0} items in Stack, removed item is {1}",myStack.Count,myStack.Pop());
Console.ReadKey();
I had to remove more than one item from the list. so,I reinitialized the list count. Is there any other better option?
for (int i = dtList.Count - 1; dtList.Count > 0; )
{
DateTime tempDate = dtList[i].Item1.Date;
var selectDates = dtList.FindAll(x => x.Item1.Date == tempDate.Date);
selectDates.Sort((a, b) => a.Item1.CompareTo(b.Item1));
dtFilteredList.Add(Tuple.Create(selectDates[0].Item1, selectDates[0].Item2));
dtList.RemoveAll(x => x.Item1.Date == tempDate.Date);
i = dtList.Count - 1;
}
List<string> list = new List<string>();
list.Add("sasa");
list.Add("sames");
list.Add("samu");
list.Add("james");
for (int i = list.Count - 1; i >= 0; i--)
{
list.RemoveAt(i);
}
精彩评论