假设我有以下代码片段:
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
}
}
下面的代码会抛出异常。我的问题是,如何在循环时避免抛出异常并删除元素,有什么最佳方法?
假设我有以下代码片段:
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
}
}
下面的代码会抛出异常。如果你需要移除元素,那么必须倒序迭代列表,这样才能从列表末尾移除元素:
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有更高效的方法来完成这个任务(正如其他答案中所示)。
Count()
是一个方法,只评估一次会更快,但如果它是一个字段Count
,由于已经缓存,性能不会有任何差异。如果它是一个属性,则取决于属性是否访问字段(缓存,快速)或调用方法(计算,慢)。 - Dan Bechard您可以使用 List<T>.RemoveAll
来处理此问题:
data.RemoveAll(elem => elem == "One");
List<T>
操作。 - Chris Marisic您也可以使用前向循环,例如:
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--);
会在迭代器变量在循环结束时失效,当列表中的项目被移除时。
它将从当前迭代值处的索引中删除项目,然后在移除项目后,迭代器将被设置为比当前值少1。在循环结束时,循环体内的增量将使其移动到下一个有效索引。
这里有一个可以工作的.NET Fiddle示例。
(请注意,我个人喜欢在这种情况下使用反向循环,因为我认为它们更易于理解,这里的答案只是为了展示另一种实现方式)。
i--
将返回0
,并且减量的效果将在下一次使用i
时可见。在VS或链接的fiddle中尝试这段代码。 - Habib我恰巧找到了一个简单的解决方案,使用foreach
和.ToArray()
var data=new List<string>(){"One","Two","Three"};
foreach ( var d in data.ToArray()){
if(d =="One"){
data.Remove(d);
}
}
.toArray()
方法会创建列表的完整副本,因此在使用大型列表时,会对性能和内存消耗产生影响。 - Martin SchneiderList.Remove("One");
或者:
List.RemoveAll(i => i == "One"); // removes all instances
做完就行了。遍历整个集合来删除一个单独的项目实际上没有任何意义。
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
i--; // <<<<<<<<<<<
}
}
new List<string>(){"One"}
的错误,也看不到new List<string>(){}
的错误。 - Pewpewvar data=new List<string>(){"One","Two","Three"};
for(int i=0; i<data.Count; ){
if(data[i]=="One") data.RemoveAt(i);
else ++i;
}
foreach (void item_loopVariable in MyList.ToList) {
item = item_loopVariable;
}
我有一个不太光彩的技巧,想知道它会受到什么批评?
var data=new List<string>(){"One","Two","Three"};
foreach (string itm in (data.ToArray()))
{
if string.Compare(name, "one", true) == 0) data.Remove(name);
}
我不得不从列表中删除多个项目。所以,我重新初始化了列表计数。有没有其他更好的选择?
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;
}
Lenght
为Count
的错误,它看起来就能正常工作了。(实际上,它确实存在一个 bug,但不应该抛出异常。) - svick