从列表中删除非常见项目

时间:2013-09-18 14:43:05

标签: c# linq

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

 var result = list1.Except(list2);

这会让我区分list1中的项目而不是list2中的项目,对吧?如果可能的话,我想做的是从list1中删除同一步骤中的所有项目。 我不想做的是必须遍历“结果”列表并从list1中删除它们。这可能吗?

谢谢!

3 个答案:

答案 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搜索),这称为“内部联接”。在您的情况下,这是一个非常简单的问题,因为您的输入列表和结果列表属于同一类型。如果您希望在不同类型的列表之间进行更复杂的连接,您可能会发现此问题很有用:

inner join in linq to entities