1

我有两个对象列表,其中一个具有不同数量的项目。现在,如果我这样做:

 var result = list1.Except(list2);

这会给我在 list1 和不在 list2 中的项目之间的区别,对吗?如果可能的话,我想做的是在同一步骤中从 list1 中删除所有这些项目。我不想做的是必须遍历“结果”列表并将它们从 list1 中删除。那可能吗?

谢谢!

4

3 回答 3

7

你可以使用List.RemoveAll

list1.RemoveAll(t => !list2.Contains(t));

这不需要创建一个新的集合,它也只需要一个循环来删除所有在 list1 中但不在 list2 中的项目。但是,我假设您误解了 LINQ 的工作原理。Enumerable.Except使用延迟执行来实现。这意味着它不会在foreach. Except对于大型列表也非常有效,因为它使用了一套方法。

于 2013-09-18T14:51:25.850 回答
6

Tim 的解决方案是正确的,但运行时间为 O(list1.Length * list2.Length)。当您使用带有适当哈希的 a 时,您将接近 O(O(list1.Length + list2.Length) 运行时。当包含多个项目HashSet<T>时,这要快得多。list2

我的变体的缺点是它需要分配哈希集,因此需要更多内存。

var set2 = new HashSet<T>(list2);
list1.RemoveAll(item=>!set2.Contains(item));
于 2013-09-18T15:12:55.613 回答
0

Tim 的解决方案的一个效率较低的替代方案是一个简单的Where子句(有点像 SQL 中的子查询)。好处是您不需要修改原始集合:

string[] list1 = new string[] { "a", "b", "c", "d", "e" };
string[] list2 = new string[] { "c", "d", "e", "f", "g" };

var result = list1.Where( i => list2.Contains( i ) ).ToArray();

如果您有非常大的数据集,我仍然会推荐 Tim 的方法。

结果:

c
d
e

要使用 SQL 术语(帮助您进行谷歌搜索),这称为“内连接”。在您的情况下,这是一个非常简单的问题,因为您的输入列表和结果列表属于同一类型。如果您想在不同类型的列表之间进行更复杂的连接,您可能会发现这个问题很有帮助:

linq 到实体的内部连接

于 2013-09-18T15:00:41.163 回答