从列表中删除子列表列表、列表中

2023-09-03 04:02:40 作者:简单鉽寂寞

我有2列出:的List1 list2中(包括int型)

I have 2 lists: list1 and list2 (both of type int)

现在我想从的List1 清除 list2中的内容。我如何在C#中做到这一点?

Now I want to remove content of list2 from list1. How I can do this in C#?

PS:不要使用循环

推荐答案

重要的变化

正如有人指出,在评论中,。除()使用了一组内部,所以的List1 将不存在于最终的结果。

As was pointed out in the comments, .Except() uses a set internally, so any duplicate members of list1 will be absent in the final result.

生成的设置两个序列的差异

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

不过,有一个解决方案,既O(N)和$ P原始列表$ pserves重复:修改 removeall过(I => list2.Contains(I))办法使用的HashSet< INT> 持有的排除设置

However, there is a solution that is both O(N) and preserves duplicates in the original list: Modify the RemoveAll(i => list2.Contains(i)) approach to use a HashSet<int> to hold the exclusion set.

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的。

Out of curiosity I did a simple benchmark of my solution vs. @HighCore's.

有关 list2中有只有一个元素,他的code是速度更快。由于 list2中变得越来越大,他的code得到的非常的慢。它看起来像他的就是 O(N平方)(或更具体地说O(list1.length * list2.length)因为的List1 每个项目相比于每个项目 list2中)。没有足够的数据点,检查大啊,我的解决方案,但它的速度要快得多,当 list2中比少数元素更多。

For list2 having just one element, his code is faster. As list2 gets larger and larger, his code gets extremely slow. It looks like his is O(N-squared) (or more specifically O(list1.length*list2.length) since each item in list1 is compared to each item in list2). Don't have enough data points to check the Big-O of my solution, but it is much faster when list2 has more than a handful of elements.

用于测试code:

        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中的最小尺寸。如果没有其他引用必须看到更新,它是preferable出于这个原因。

This solution assigns a new list to the variable list1. As @Толя points out, other references (if any) to the original list1 will not be updated. This solution drastically outperforms RemoveAll for all but the smallest sizes of list2. If no other references must see the update, it is preferable for that reason.