我有 2 个列表:list1
和 list2
(均为 int 类型)
现在我想从 list1
中删除 list2
的内容。我如何在 C# 中执行此操作?
PS:不要使用循环。
最佳答案
重要变化
正如评论中指出的那样,.Except()
在内部使用集合,因此 list1
的任何重复成员将不会出现在最终结果中。
Produces the set difference of two sequences
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));
扩展方法ToHashSet()
在 MoreLinq 中可用.
原始答案
你可以使用 Linq
list1 = list1.Except(list2).ToList();
更新
出于好奇,我对我的解决方案与@HighCore 的解决方案进行了简单的基准测试。
对于 list2
只有一个元素,他的代码更快。作为list2
变得越来越大,他的代码变得极度慢。看起来他的是 O(N-squared)(或更具体地说是 O(list1.length*list2.length) 因为将 list1
中的每个项目与 list2
中的每个项目进行比较)。没有足够的数据点来检查我的解决方案的 Big-O,但当 list2
时速度要快得多有很多元素。
用于测试的代码:
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;
更新 2
此解决方案将一个新列表分配给变量 list1
.正如@Толя 指出的那样,对原始 list1
的其他引用(如果有的话)不会更新。该解决方案的性能大大优于 RemoveAll
对于 list2
以外的所有尺寸.如果没有其他引用必须看到更新,出于这个原因,这是更可取的。
关于c# - 从列表中删除子列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14388834/