Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从列表中删除元素最有效的方法是什么<;T>;在c#中做foreach?_C# - Fatal编程技术网

从列表中删除元素最有效的方法是什么<;T>;在c#中做foreach?

从列表中删除元素最有效的方法是什么<;T>;在c#中做foreach?,c#,C#,我想知道在进行foreach时,用c#从列表中删除元素的最佳方法是什么 下面是一个代码示例。首先,我创建了一个包含一些元素的列表,然后删除一个: 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); } } List foo=new List()

我想知道在进行foreach时,用c#从列表中删除元素的最佳方法是什么

下面是一个代码示例。首先,我创建了一个包含一些元素的列表,然后删除一个:

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);
    }
}
List foo=new List();
foo.Add(1);
foo.Add(2);
foo.Add(3);
foreach(foo中的int i)
{
如果(i==2)
{
foo.删除(i);
}
}

当我运行这个时,我得到了一个
invalidoOperationException
,但是如何用性能方法解决这个问题呢?

为什么需要一个循环

foo.Remove(2);

如果必须在枚举时删除条目,请向后遍历列表,并删除需要删除的项

for (var i = foo.Count-1 ; i >= 0 ; i--) {
    if (MustBeRemoved(foo[i])) {
        foo.RemoveAt(i);
    }
}

请注意,如果您的帖子知道需要删除的值,则不需要这样做。

您可以将要删除的项目添加到临时列表中,然后在循环后删除它们:

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 foo=new List();
foo.Add(1);
foo.Add(2);
foo.Add(3);
List remove=新列表();
foreach(foo中的int i){
如果(i==2){
删除。添加(i);
}
}
foreach(移除中的int i){
foo.删除(i);
}

您不能在迭代列表时对其进行编辑

考虑:

List<int> foo;
int[] bar = foo.ToArray();

foreach(int i in bar)
{
    if (i == 2)
    {
        foo.Remove(i);
    }
}
列出foo;
int[]bar=foo.ToArray();
foreach(单位:巴)
{
如果(i==2)
{
foo.删除(i);
}
}

但是要注意:你应该向后看这个列表,因为从foo列表中删除一个项目将意味着酒吧列表不再与之对齐。(如果不向后走,就必须跟踪删除次数并调整传递给删除调用的索引!)

我认为最好的方法是使用简单的
for
循环向后迭代

for(int i = foo.Count-1; i>=0; i--)
    if(foo[i]==2) foo.RemoveAt(i);

更改您的foreach,如下所示

foreach (int i in new List<int>(foo))
foreach(新列表中的int i(foo))

我假设您的实际用例比您所列出的更复杂。所以,让我们假设您实际上有一些条件,适用于每个元素,并且多个元素可以满足。我们称之为谓词

List
公开允许您提供谓词的
RemoveAll
方法。然后删除与该谓词匹配的任何项。比如说

Func<int, bool> isEven = i => i % 2 == 0;
List<int> ints = ...
ints.RemoveAll(item => isEven(item));
// ints will only contain odd numbers 
Func isEven=i=>i%2==0;
列表整数=。。。
ints.RemoveAll(item=>isEven(item));
//整数将只包含奇数

其他要考虑的方法是在<<代码>后面的列表中遍历循环并按索引移除,构建包含要删除的项的第二个列表,然后在第二个列表中的第二个循环中,从第一个项目中删除项。或者,您可以编写一个查询来构造一个新的序列,其中包含您希望保留的项。

如果您想删除任意元素,而不仅仅是一个元素,您可以使用
RemoveAll
并指定一个谓词:

foo.RemoveAll(element => (element == 2));

如果您决定不使用for和foreach;)

因此,你应该问什么是正确的,而不是性能。解决了这个难题之后,再担心它是否有效。我同意@AnthonyPegram。在谈到性能时,您还需要确定是内存受限还是处理器受限——答案各不相同。您的问题是“我想在这堵墙上钻一个洞;用锤子做这件事最快的方法是什么?”最快的方法是首先不使用锤子。foreach循环不是作业的正确工具;问如何使用错误的工具更快地解决问题并不是一个富有成效的问题。我假设他过于简化了他的示例:)我猜他只是给出了一个非常简化的示例。这是一个非常简单的示例,在实际代码中,它一定更复杂。所以这不是work@ThomasLevesque真正的代码看起来像
foo.RemoveAll(i=>i==2)。您给出的示例无法编译,因为
List.RemoveAll
没有接受
t
参数的重载。@phoog,这不是我写的,其他人编辑了我的答案。。。我将把它回滚到以前的状态。
foo.RemoveAll(MustBeRemoved)
如果需要删除许多元素,性能会更好。注意:此代码不枚举列表。它使用的是索引变量,而不是枚举数。不允许在枚举列表时编辑列表,这将导致异常:在mscorlib.dll中发生“System.InvalidOperationException”类型的未处理异常。其他信息:集合已修改;枚举操作可能无法执行。如果.NET版本支持此操作,我将在“通过数组反向循环”方法上面使用此方法。它更干净,代码更少,可读性更强,更不容易出错。
foo.RemoveAll(x => x == 2);