如何从数组中删除元素

时间:2011-02-01 21:16:06

标签: c# arrays .net-2.0

嗨,我正在研究一些与

相似的遗留代码
for(int i = results.Count-1; i >= 0; i--)
{
  if(someCondition)
  {
     results.Remove(results[i]);
  }
}

对我来说,在迭代循环时删除元素似乎是不好的做法,因为你将修改索引。

这是正确的假设吗?

有更好的方法吗?我想使用LINQ,但我在2.0 Framework

5 个答案:

答案 0 :(得分:12)

删除实际上是正常的,因为您将向下归零,只会修改已传递的索引。这段代码实际上会因为另一个原因而中断:它以results.Count开头,但应该从results.Count -1开始,因为数组索引从0开始。

for(int i = results.Count-1; i >= 0; i--)
{
  if(someCondition)
  {
     results.RemoveAt(i);
  }
}

修改

正如所指出的那样 - 你实际上必须处理伪代码中的某种List。在这种情况下,它们在概念上是相同的(因为列表在内部使用数组)但是如果使用数组,则具有Length属性(而不是Count属性),并且您无法添加或删除项

使用列表上面的解决方案当然简明扼要,但对于必须维护代码的人来说可能并不容易理解(即特别是向后遍历列表) - 另一种解决方案可能是首先确定要删除的项目,然后在第二次通过删除这些项目。

只需将MyType替换为您正在处理的实际类型:

List<MyType> removeItems = new List<MyType>();

foreach(MyType item in results)
{
   if(someCondition)
   {
        removeItems.Add(item);
   }
}

foreach (MyType item in removeItems)
    results.Remove(item);

答案 1 :(得分:1)

我可以建议您使用当前代码的功能替代方案:

不是一次修改一个项目的现有数组,而是可以从中导出一个新项目,然后在完成后将整个数组替换为“原子”操作:

简单的方法(没有LINQ,但非常相似):

Predicate<T> filter = delegate(T item) { return !someCondition; };

results = Array.FindAll(results, filter);
// with LINQ, you'd have written: results = results.Where(filter);

其中Tresults数组中项目的类型。


更明确的选择:

var newResults = new List<T>();
foreach (T item in results)
{
    if (!someCondition)
    {
        newResults.Add(item);
    }
}
results = newResults.ToArray();

答案 2 :(得分:1)

看起来删除应该根本不起作用。如果我们处理固定大小的数组,IList实现应该会失败,请参阅here

话虽如此,如果您正在处理可调整大小的列表(例如List&lt; T&gt;),为什么要调用Remove而不是RemoveAt?由于您已经反向导航索引,因此您无需“重新找到”该项目。

答案 3 :(得分:0)

通常你不会删除这样的元素,你可以从旧的数组创建一个没有不需要的元素的新数组。

如果您确实从数组/列表中删除元素的路径,则循环应该倒计时而不是向上计数。 (就像你的那样)

答案 4 :(得分:0)

有两种选择:

List<int> indexesToRemove = new List<int>();
for(int i = results.Count; i >= 0; i--)
{
  if(someCondition)
  {
     //results.Remove(results[i]);
       indexesToRemove.Add(i);
  }
}

foreach(int i in indexesToRemove) {
results.Remove(results[i]);
}

或者,您可以复制现有列表,而不是从原始列表中删除。

//temp is a copy of results
for(int i = temp.Count-1; i >= 0; i--)
{
  if(someCondition)
  {
     results.Remove(results[i]);
  }
}