从列表中删除子列表

时间:2013-01-17 21:56:08

标签: c# .net

我有两个列表:list1list2(都是int类型)

现在我要从list2中删除list1的内容。我怎么能在C#中做到这一点?

PS:不要使用循环。

4 个答案:

答案 0 :(得分:19)

重要更改

正如评论中指出的那样,.Except()在内部使用了一个集合,因此list1中任何重复的成员都不会出现在最终结果中。

  

产生两个序列的差异

http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except(v=vs.110).aspx

但是,有一个解决方案既是O(N)又保留了原始列表中的重复项:修改RemoveAll(i => list2.Contains(i))方法以使用HashSet<int>来保存排除集。

List<int> list1 = Enumerable.Range(1, 10000000).ToList();
HashSet<int> exclusionSet = Enumerable.Range(500000, 10).ToHashSet(); 

list1.Remove(i => exclusionSet.Contains(i));

MoreLinq中提供了扩展方法ToHashSet()

原始回答

您可以使用Linq

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

<强>更新

出于好奇,我对@ HighCore的解决方案进行了简单的基准测试。

对于只有一个元素的list2,他的代码更快。随着list2越来越大,他的代码极其慢。看起来他的 O(N平方)(或更具体地说是O(list1.length * list2.length),因为list1中的每个项目都与{{1}中的每个项目进行比较}})。没有足够的数据点来检查我的解决方案的Big-O,但是当list2拥有多个元素时,它会快得多。

用于测试的代码:

list2

更新2

此解决方案为变量 List<int> list1 = Enumerable.Range(1, 10000000).ToList(); List<int> list2 = Enumerable.Range(500000, 10).ToList(); // Gets MUCH slower as 10 increases to 100 or 1000 Stopwatch sw = Stopwatch.StartNew(); //list1 = list1.Except(list2).ToList(); list1.RemoveAll(i => list2.Contains(i)); sw.Stop(); var ms1 = sw.ElapsedMilliseconds; 分配新列表。正如@Толя指出的那样,原始list1的其他引用(如果有的话)将不会更新。对于除list1的最小尺寸之外的所有尺寸,此解决方案都大大优于RemoveAll。如果没有其他引用必须看到更新,那么最好是因为这个原因。

答案 1 :(得分:7)

list1.RemoveAll(x => list2.Contains(x));

答案 2 :(得分:4)

您可以使用:

List<T> result = list1.Except(list2).ToList();

答案 3 :(得分:0)

这将从secondList

中删除firstList中的所有项目
firstList.RemoveAll( item => { secondList.Contains(item); } );