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

Ash*_*mad 43 .net c# collections list

假设我有以下代码片段:

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

以下代码抛出异常.

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

Chr*_*isF 94

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

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

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

  • 或者您可以向前迭代,如果删除元素,则不会增加计数器.但反向迭代可能更好. (23认同)

Ree*_*sey 43

你可以List<T>.RemoveAll用来处理这个:

data.RemoveAll(elem => elem == "One");
Run Code Online (Sandbox Code Playgroud)

  • @user,您的代码示例中没有使用枚举器. (4认同)

Pus*_*dra 10

我偶然遇到一个简单的解决方案,使用foreach.ToArray()

  var data=new List<string>(){"One","Two","Three"};
   foreach ( var d in data.ToArray()){
      if(d =="One"){
        data.Remove(d);
      }
    }
Run Code Online (Sandbox Code Playgroud)

  • 注意`.toArray()`创建列表的完整副本。因此,列表过多时会对性能和内存消耗产生影响。 (2认同)

Hab*_*bib 9

您还可以使用向前移动的循环,例如:

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--);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

这是一个工作 dotfiddle

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