C#List - 循环/迭代时删除项目

时间:2011-09-07 21:33:06

标签: c# .net list collections

假设我有以下代码段:

var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
  if(data[i]=="One"){
    data.RemoveAt(i);
  }
}

以下代码抛出异常。

我的问题是什么是避免此异常并在循环时删除元素的最佳方法?

13 个答案:

答案 0 :(得分:91)

如果您需要删除元素,则必须向后迭代,以便从列表末尾删除元素:

var data=new List<string>(){"One","Two","Three"};
for(int i=data.Count - 1; i > -1; i--)
{
    if(data[i]=="One")
    {
        data.RemoveAt(i);
    }
}

但是,使用LINQ有更有效的方法(如其他答案所示)。

答案 1 :(得分:42)

您可以使用List<T>.RemoveAll来处理此问题:

data.RemoveAll(elem => elem == "One");

答案 2 :(得分:10)

我碰巧使用foreach.ToArray()

找到了一个简单的解决方案
  var data=new List<string>(){"One","Two","Three"};
   foreach ( var d in data.ToArray()){
      if(d =="One"){
        data.Remove(d);
      }
    }

答案 3 :(得分:4)

您可以尝试使用ChrisF的反向迭代方法删除您的项目。

你也可以简单地说:

List.Remove("One");

或者:

List.RemoveAll(i => i == "One"); // removes all instances

完成它。迭代集合以删除单个项目实在没有意义。

答案 4 :(得分:4)

你也可以使用前移动循环,如:

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--);
    }
}

如果项目从列表中删除,则此行data.RemoveAt(i--);将停止循环结束时迭代变量中增量的效果。

它将从当前迭代值的索引中删除该项,然后在删除该项之后,迭代器将设置为比当前迭代值少一个值。在循环结束时,循环体中的增量将其移动到下一个有效索引。

这是一个有效的 dotfiddle

(请注意,我个人使用反向循环来处理类似这样的情况,因为IMO,它们更容易理解,这里的答案仅用于显示实现它的另一种方式)

答案 5 :(得分:2)

为什么不简单地减少迭代器变量?

var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
  if(data[i]=="One"){
    data.RemoveAt(i);
    i--; // <<<<<<<<<<<
  }
}

答案 6 :(得分:1)

这是一个肮脏的伎俩,我想知道对它的批评是什么?

var data=new List<string>(){"One","Two","Three"};
foreach (string itm in (data.ToArray()))
{
  if string.Compare(name, "one", true) == 0) data.Remove(name);
}

答案 7 :(得分:1)

下面的一般解决方案会复制列表并处理负面索引:

foreach (void item_loopVariable in MyList.ToList) {
    item = item_loopVariable;

}

答案 8 :(得分:0)

        var data = new List<string>() { "One", "Two", "Three" };
        data.RemoveAll(p=>p=="One");

答案 9 :(得分:0)

var data=new List<string>(){"One","Two","Three"};
for(int i=0; i<data.Count; ){
  if(data[i]=="One") data.RemoveAt(i);
  else ++i;
}

答案 10 :(得分:0)

您可以使用Stack类

        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();

答案 11 :(得分:0)

我不得不从列表中删除多个项目。所以,我重新初始化了列表计数。还有其他更好的选择吗?

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;
}

答案 12 :(得分:-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);

    }