我制作了一个方法,可以消除List中相同string
的任何重复。
现在,问题是它给了我这个错误:
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
我在互联网上阅读,我认为问题是我要从列表的foreach
循环中的列表中删除一个对象。
foreach (string r in list)
{
int numberOfAppearance=0;
foreach (string rs in list)
{
if (r == rs && numberOfAppearance> 0)
list.Remove(rs);
else
numberOfAppearance++;
}
}
我该如何修复方法?谢谢你的帮助
答案 0 :(得分:6)
首先,正如评论中所述,LINQ已经为您介绍了这一点:
list = list.Distinct().ToList();
值得研究LINQ进行数据操作 - 它可以使事情变得更简单。
至于您当前的代码有什么问题 - 有几件事情:
首先,您要删除项目而不是索引,这将删除该项目的第一次出现,而不是您实际查看的项目
其次,如果您在迭代时修改列表, 将准确地获得您所看到的异常。来自List<T>.GetEnumerator
的文档:
只要集合保持不变,枚举器仍然有效。如果对集合进行了更改,例如添加,修改或删除元素,则枚举数将无法恢复,并且其行为未定义。
你可以通过迭代 index 而不是使用foreach
循环来解决这个问题,但如果你要删除一个项目,你需要记住下面的所有内容都会向上移动一个元件。因此,您需要迭代向后来删除项目,或者您需要记住减少索引。
这是一种根据我们正在查看的内容使用索引转发进行迭代的方法,但是在寻找重复项时使用向后 - 当我们到达时停止我们正在关注的指数。请注意,这仍然是O(N 2 ) - 它不如使用Distinct
有效:
// We're looking for duplicates *after* list[i], so we don't need to go as far
// as i being the very last element: there aren't any elements after it to be
// duplicates. (We could easily still just use list.Count, and the loop for j
// would just have 0 iterations.)
for (int i = 0; i < list.Count - 1; i++)
{
// Go backwards from the end, looking for duplicates of list[i]
for (int j = list.Count - 1; j > i; j--)
{
if (list[j] == list[i])
{
list.RemoveAt(j);
}
}
}
(有关Distinct
的详细信息,请参阅我的Edulinq post on it。)
答案 1 :(得分:1)
正如许多人所指出的,您可以使用Distinct
方法解决您的特定问题。
但是,你实际遇到的问题是你在迭代它时试图修改列表,这不会很好地结束。
//This will not work.
foreach (string rs in list)
{
if (some_test)
{
list.Remove(rs); //Because of this line.
}
}
如果你想做类似的事情,你需要找到解决这个问题的方法。通常它涉及制作一个新阵列。
对于本次考试,您可以执行以下操作
List newList = new ArrayList();
foreach (string rs in list)
{
if (!some_test)
{
newList.add(rs);
}
}
如果你真的想创建一个&#34;删除重复项&#34;方法我会以这种方式(伪代码)完成它:
Hash cache_hash = new Hash(default false)
List new_list = new List
foreach string s in list
{
if not cache_hash[s]
{
new_list.add(s)
cache_hash[s] = true
}
}
list = new_list
此方法为Ω(N)
,因此即使是大型列表也相当快。