删除重复比较两个大型列表在C#中有效?

时间:2014-11-10 12:35:50

标签: c# linq

我有两个大的列表,list1有4列,list2有3列。 如果list1在列1和列3中包含与list2相同的值,那么我需要在list1中删除该项。我实际上正在寻找一些优势和有效的解决方案。谢谢你的帮助。

List1:
1, 5, 3, 9     // Remove this
11, 15, 18, 6  // Keep this  

List2:
1, 5, 3

List<Tuple<int, int, int, int>> list1 = new List<Tuple<int, int, int, int>>();
List<Tuple<int, int, int>> list2 = new List<Tuple<int, int, int>>();

2 个答案:

答案 0 :(得分:2)

理想情况下,从性能角度来看,您可以利用HashSet.SymmetricExceptWith,但是您使用的是两种不同的类型(以及Tuples)。

Except是一种可能的解决方案:

list1 = list1.Except(list1
    .Where(l1 => list2
        .Any(l2 => l2.Item1 == l1.Item1
            && l2.Item2 == l1.Item2
            && l2.Item3 == l1.Item3)))
    .ToList();

答案 1 :(得分:1)

        var index2 = list2.ToLookup(t => Tuple.Create(t.Item1, t.Item3));
        //var index2 = list2.Select(l => Tuple.Create(l.Item1, l.Item3)).ToList();
        //index2.Sort();
        var results = from l in list1
                      where !index2.Contains(Tuple.Create(l.Item1, l.Item3))
                      select l;

这可能相当有效。缺点是index2增加了内存使用量。注释掉了另一种索引方法,该方法在内存上稍微容易一些。 ToList版本不会存储对原始记录的引用,因此它会更轻量级。但ToLookup索引可能比这个特定问题有更多用途。 ToDictionary也可以是一个选项,而不是ToLookup,如果每个键都是唯一的,但这是重量级的倒退。

根据这些列表的确实大小,可以通过几个很好的AsParallel()调用获得额外的收益。

        var index2 = list2.AsParallel().ToLookup(t => Tuple.Create(t.Item1, t.Item3));
        var results = from l in list1.AsParallel()
                      where !index2.Contains(Tuple.Create(l.Item1, l.Item3))
                      select l;

尝试使用其中一个或两个,因为只有您的环境可以告诉我们这是否是最好的。有时,在多个线程上分配工作的费用可能比连续完成工作花费更长的时间。