从列表中删除项目而不进入集合修改的异常的最有效方法?

时间:2011-07-07 19:43:32

标签: c# linq dictionary ienumerable set-difference

我有2个名单:

ListA { 'A', 'B', 'C' } //ListA is DictA.Keys
ListB { 'B', 'X', 'Y' } //ListB is DictB.Keys

如果我ListA.Except(ListB)我返回了一个ExceptIterator,这将让我在ListA上迭代任何不在ListB中的项目。问题是它的实现只是简单地使用ListA(出于某种原因,我认为它会创建一个新的项目集合,这是不同的)。嗯,低,看到我发现它仍然使用ListA作为源,但只是使用一种特殊类型的迭代器。所以,当然,当我从ListA中删除一个项目时,它会抱怨该集合已被修改。

我可以想到几种方法来做我想要的,首先是复制ListA并在副本上执行除外。第二个是做一个while循环。我只是想知道这个问题的最佳解决方案是什么,以及遵循标准指南的是什么。

如果我以错误的方式解决这个问题,我很想知道。我的主要目标是使用键作为比较从DictB中不存在的DictA中删除所有内容。

6 个答案:

答案 0 :(得分:3)

如果您需要结果并且不依赖于以后的更改,只需通过在查询上调用ToList()ToArray()来获得具体结果。

var query = list1.Except(list2).ToList(); 

对任一源输入的更改都不会影响您现在完全评估的查询。

答案 1 :(得分:2)

为什么不直接使用评价?

var myList = ListA.Except(ListB).ToList();

答案 2 :(得分:2)

出于同样的原因,我使用下一个:

ListA = ListA.Except(ListB).ToList();

答案 3 :(得分:0)

也许你会倒退这个。另一种说“从DictA中删除不在DictB中的所有东西”的方法是说“保持 DictA中的所有东西也在DictB中”。而不是尝试从ListA中删除东西,只需创建一个新列表:

ListA.Join(ListB, ...);

答案 4 :(得分:0)

如果您想要两个词典的交集,那么这就是您所做的:

IEnumerable<KeyValuePair<Char, String>> result = DictB.Intersect<KeyValuePair<Char, String>>(DictA);

这将返回DictA中与DictB匹配的所有项目。此外,对于该示例,我假设Keys的类型为Char,而值的类型为String。如果您的不同,只需为您的解决方案设置正确的类型。 要查看实际结果,您必须发送result.GetEnumerator()或在foreach语句中使用它。

答案 5 :(得分:0)

如果可以控制有问题的数据结构,定义一个接受谓词的Purge方法(接受列表的数据类型并返回布尔值的函数)并删除谓词的所有项可能很有用。返回true(我希望Microsoft已经定义了一个IPurgeableCollection,因为对于许多正常的Microsoft集合来说,实现这样的例程并不存在固有的困难)。请注意,在许多情况下,集合实现Purge方法比允许在枚举期间进行一般修改要容易得多,并且在许多情况下这样的方法不仅可以避免创建数据的额外副本到被删除,但它也可以大大减少执行删除所需的工作量(例如,当清除字典时,不必查找要删除的每个键,因为在枚举期间已经找到它)。