我有两个对象列表,其中一个对象具有不同数量的项目。现在,如果我做了:
var result = list1.Except(list2);
这会让我区分list1中的项目而不是list2中的项目,对吧?如果可能的话,我想做的是从list1中删除同一步骤中的所有项目。 我不想做的是必须遍历“结果”列表并从list1中删除它们。这可能吗?
谢谢!
答案 0 :(得分:7)
您可以使用List.RemoveAll
:
list1.RemoveAll(t => !list2.Contains(t));
这不需要创建一个新集合,它也只需要一个循环来删除list1中但不在list2中的所有项。但是,我认为你误解了LINQ是如何工作的。 Enumerable.Except
是使用延迟执行实现的。这意味着它将在foreach
之前执行。 Except
对于大型列表也非常有效,因为它使用了一种集合方法。
答案 1 :(得分:6)
蒂姆的解决方案是正确的,但运行时间为O(list1.Length * list2.Length)。当您使用具有适当散列的HashSet<T>
时,您将接近O(O(list1.Length + list2.Length)运行时。当list2
包含多个项目时,这会快得多。< / p>
我的变体的缺点是它需要分配hashset,因此需要更多的内存。
var set2 = new HashSet<T>(list2);
list1.RemoveAll(item=>!set2.Contains(item));
答案 2 :(得分:0)
Tim's solution的低效替代方法是一个简单的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的方法。
结果:
Ç
d
e
要使用SQL术语(以帮助您的Google搜索),这称为“内部联接”。在您的情况下,这是一个非常简单的问题,因为您的输入列表和结果列表属于同一类型。如果您希望在不同类型的列表之间进行更复杂的连接,您可能会发现此问题很有用: