如何从数组中删除元素
嗨,我正在研究一些遗留代码
for(int i = results.Count-1; i >= 0; i--) { if(someCondition) { results.Remove(results[i]); } }
对我来说,在迭代循环的同时删除元素似乎是不好的做法,因为你将修改索引。
这是正确的假设吗?
有更好的方法吗? 我想使用LINQ,但我在2.0 Framework中
删除实际上是正确的,因为您将向下归零,只有您已经传递的索引才会被修改。 这段代码实际上会因为另一个原因而中断:它以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 removeItems = new List (); foreach(MyType item in results) { if(someCondition) { removeItems.Add(item); } } foreach (MyType item in removeItems) results.Remove(item);
它看起来似乎根本不起作用。 如果我们处理固定大小的数组,IList实现应该会失败,请参见此处 。
话虽这么说,如果你正在处理一个可resize的列表(例如List
我可以建议你当前代码的function更强大的替代品:
您可以从中导出一个新项目,然后在完成后将整个数组替换为“primefaces”操作,而不是一次修改一个项目的现有数组:
简单的方法(没有LINQ,但非常相似):
Predicate filter = delegate(T item) { return !someCondition; }; results = Array.FindAll(results, filter); // with LINQ, you'd have written: results = results.Where(filter);
其中T
是results
数组中项目的类型。
一个更明确的选择:
var newResults = new List(); foreach (T item in results) { if (!someCondition) { newResults.Add(item); } } results = newResults.ToArray();
通常你不会删除这样的元素,你可以从旧的数组创建一个没有不需要的元素的新数组。
如果您确实从数组/列表中删除元素的路径,则循环应该倒计时而不是向上计数。 (就像你的那样)
几个选项:
List indexesToRemove = new List (); 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]); } }