从列表中删除子列表

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

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

PS:不要使用循环。

重要的变化

正如评论中指出的那样, .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来保存排除集。

 List list1 = Enumerable.Range(1, 10000000).ToList(); HashSet exclusionSet = Enumerable.Range(500000, 10).ToHashSet(); list1.Remove(i => exclusionSet.Contains(i)); 

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

原始答案

你可以使用Linq

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

UPDATE

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

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

用于测试的代码:

  List list1 = Enumerable.Range(1, 10000000).ToList(); List 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; 

更新2

此解决方案为变量list1分配新列表。 正如@Толя指出的那样,原始list1其他引用(如果有的话)将不会更新。 除了最小尺寸的list2这个解决方案的性能远远超过RemoveAll 。 如果没有其他引用必须看到更新,那么最好是因为这个原因。

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

你可以用这个:

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

这将从secondList删除secondList中的每个项目:

 firstList.RemoveAll( item => { secondList.Contains(item); } );