从0循环到列表末尾(列表或映射)以及从结尾循环到0的场景是什么?下面是代码片段,它从0到最后遍历列表以过滤掉某些特定的学生姓名。此代码是否会在任何情况下抛出任何异常?从列表末尾迭代到零会对此代码产生任何影响吗?
List<Dictionary<string, string>> allStudentsList = allStudentsArray.ToList();
for (int i = 0; i < allStudentsList .Count-1; i++) {
Dictionary<string, string> student= allStudentsList .ElementAt(i);
string studentName;
bool hasValue = studentName.TryGetValue("id", out studentName);
if (hasValue) {
if (studentName.StartsWith("John") {
allStudentsList.RemoveAt(i);
i--;
}
}
}
答案 0 :(得分:1)
首先,您的问题包含语义错误。它是:
从
end-1
到0
。
如果您从end
开始,由于ArgumentOutOfRangeException
方法规范,您将立即获得ElementAt
。
如果您从从右向左移动,则在i++
为真的情况下,您不必执行增量(hasValue
)。仅仅因为索引左侧的项目没有移动。所以你可以实现它:
List<Dictionary<string, string>> allStudentsList = allStudentsArray.ToList();
for (int i = allStudentsList.Count-1; i >= 0; i--) {
Dictionary<string, string> student = allStudentsList.ElementAt(i);
string studentName;
bool hasValue = studentName.TryGetValue("id", out studentName);
if (hasValue) {
if (studentName.StartsWith("John") {
allStudentsList.RemoveAt(i);
}
}
}
接下来,它可以改善性能。如果从List<T>.RemoveAt
中删除元素,则表示索引右侧的所有元素都放在左侧的一个位置。现在,如果你先从右边删除,右边的项目数量会很少,而且如果索引位于零附近,那么要向左移动的项目数量会更小(仅仅因为某些元素已经存在)去除)。但是,如果hasValue
很少true
,那么不要期望获得巨大的性能提升。
在这种情况下,for
是向前还是向后完成并不重要,因为有共享状态&#34;在不同的迭代中。
答案 1 :(得分:1)
现在,我想提供一个伴侣答案,以回应CommuSoft最优秀,最彻底的事先评论。 (即&#34;没有关系,&#34;而是:&#34;并行... tangental ...&#39; FYI&#39; ...&#34;) *
一般(和无论使用的语言是什么(!) ...),如果你通过任何某种数据结构,你删除的东西,总是想要从终点到0迭代#34;&#34; (否则,它确实无关紧要......)
为什么呢?因为,任何时候你从任何类型的集合中删除任何东西,&#39;长度&#39;该集合的减少量为1. 如果你正在从后向前迭代,这不是一个问题:你永远不会错过任何东西,&#34;你也不会两次遇到相同的元素。&#34;如果你正在以另一种方式旅行,那么(!)都非常真实(因此,#34;完全可以避免&#34;)。