从List<;T>;在c中做foreach
本文关键字:foreach 中做 List lt gt | 更新日期: 2023-09-27 18:24:55
我想知道在执行foreach时,从c#中的List中删除元素的最佳方法是什么。
这是一个代码示例。首先我创建了一个包含一些元素的列表,然后创建一个:
List<int> foo = new List<int>();
foo.Add(1);
foo.Add(2);
foo.Add(3);
foreach (int i in foo)
{
if (i==2)
{
foo.Remove(i);
}
}
当我运行这个时,我得到了一个InvalidOperationException
,但如何用性能的方法来解决这个问题?
如果在枚举时必须删除条目,请反向遍历列表,并删除需要删除的项。
for (var i = foo.Count-1 ; i >= 0 ; i--) {
if (MustBeRemoved(foo[i])) {
foo.RemoveAt(i);
}
}
请注意,这是,而不是在您的帖子中需要的,因为您知道需要删除的值。
foo.RemoveAll(x => x == 2);
如果您决定不使用for和foreach;)
我认为您的实际用例比您所布局的更复杂。因此,让我们假设您实际上有一些条件在起作用,这些条件适用于每个元素,并且多个元素可以满足。我们将其称为谓词。
List<T>
公开了一个RemoveAll
方法,该方法允许您提供谓词。然后删除与该谓词匹配的任何项。例如
Func<int, bool> isEven = i => i % 2 == 0;
List<int> ints = ...
ints.RemoveAll(item => isEven(item));
// ints will only contain odd numbers
其他需要考虑的方法是在for
循环中向后遍历列表并按索引删除,构建包含要删除的项目的第二个列表,然后在第二个循环中遍历第二个,从第一个列表中删除项目。或者,您可以编写一个查询来构建一个新的序列,其中包含您希望保留的项。
为什么需要循环?
foo.Remove(2);
我认为最好的方法是使用简单的for
循环向后迭代。
for(int i = foo.Count-1; i>=0; i--)
if(foo[i]==2) foo.RemoveAt(i);
将前臂更改为
foreach (int i in new List<int>(foo))
如果您想删除任意元素,而不仅仅是一个,您可以使用RemoveAll
并指定一个谓词:
foo.RemoveAll(element => (element == 2));
您可以将要删除的项目添加到临时列表中,然后在循环后删除它们:
List<int> foo = new List<int>();
foo.Add(1);
foo.Add(2);
foo.Add(3);
List<int> remove = new List<int>();
foreach (int i in foo) {
if (i==2) {
remove.Add(i);
}
}
foreach (int i in remove) {
foo.Remove(i);
}
迭代列表时不能编辑列表。
考虑:
List<int> foo;
int[] bar = foo.ToArray();
foreach(int i in bar)
{
if (i == 2)
{
foo.Remove(i);
}
}
但是要注意:你应该向后走这个列表,因为从foo列表中删除一个项目将意味着条形列表不再与它对齐。(如果你不向后走,你将不得不跟踪删除的计数,并调整传递给remove调用的索引!)