我只是注意到我测试了RemoveAt()和Remove()这两个方法时有些尴尬,但是它们的工作方式不同,我想知道是否有人可以举例说明其原因。基本上,在此示例中,唯一成功从列表中删除特定项目的方法是Remove()。
List<int> testList = new List<int>{1,76,3,4,5,76,76,8};
public void RemoveElements()
{
for (int i = 0; i < testList.Count; i++)
{
//WORKS
testList.Remove(76); //A
// DOES NOT WORK
//if(testList[i] == 76) testList.Remove(testList[i]); //B
// DOES NOT WORK EITHER
// if(testList[i] == 76) testList.RemoveAt(i); //C
}
}
A的输出为:1、3、4、5、8 B的输出为:1、3、4、5、76、8 C的输出是:1、3、4、5、76、8
谢谢您的时间!
答案 0 :(得分:2)
按索引删除项目会更改后面的项目的索引。这可能导致跳过某些项目。如果要在遍历列表时使用RemoveAt,请尝试反向迭代。
答案 1 :(得分:1)
Remove
和RemoveAt
函数实际上在您的代码中正常工作。但是,如果要遍历列表,则使用RemoveAt
是更好的函数,因为Remove
必须再次搜索列表以查找出现76
的第一种情况,而{ {1}}已经知道删除该项目的确切索引。
由于您遍历列表的方式而出现问题。
当您遍历列表并从列表中删除项目时,列表会向左移动一个索引以填充RemoveAt
索引仍在同一位置时刚刚删除的项目(跳过下一个项目) 。
通常,最好的做法是,如果要从列表中删除元素,则向后遍历列表,因为终点取决于它达到0,并且每次处理列表向左移动时都不会跳过下一个元素。>
i
答案 2 :(得分:1)
这是您的列表开头的内容:
i: 0 1 2 3 4 5 6 7
testList[i]: 1 76 3 4 5 76 76 8
现在考虑当i == 5
在循环迭代期间会发生什么,这意味着testList[i]
是两个相邻76es中的第一个。运行版本B或C中的代码将从testList
中删除元素5,从而导致其后的元素向下移动一个索引。因此testList[6]
原本是76,现在是8;和testList[7]
(原为8)现在已超出列表的末尾。下一次循环运行时,它将使用i == 6
,这意味着您的代码将考虑值8,而不是76es中的秒。第二个76已被完全跳过。
这是hatchet对您的问题进行评论的原因,该问题表示如果必须遍历列表,则应相反进行。如果要向后迭代,则删除元素将元素的位置在列表中进一步往下移都没关系,因为您已经处理了这些元素。当然,更好的方法仍然是使用根本不需要迭代的解决方案,例如List<T>.RemoveAll
。
答案 3 :(得分:0)
Remove
从集合中删除等于您指定的元素的元素。 RemoveAt
删除指定位置的元素。