比较两个庞大(>50.000项)的最快(和最少资源密集型)的方法是什么,从而得到如下所示的两个列表:

在第一个列表中出现但在第二个列表中没有出现的项目 出现在第二个列表中但不在第一个列表中的项目

目前,我正在使用列表或IReadOnlyCollection,并在linq查询中解决这个问题:

var list1 = list.Where(i => !list2.Contains(i)).ToList();
var list2 = list2.Where(i => !list.Contains(i)).ToList();

但这并不像我想的那样好。 有什么想法使这更快和更少的资源密集,因为我需要处理很多列表?


当前回答

一行:

var list1 = new List<int> { 1, 2, 3 };
var list2 = new List<int> { 1, 2, 3, 4 };
if (list1.Except(list2).Count() + list2.Except(list1).Count() == 0)
    Console.WriteLine("same sets");

其他回答

这是你能找到的最好的解决办法

var list3 = list1.Where(l => list2.ToList().Contains(l));

Jon Skeet和miguelmpn的回答都很好。这取决于列表元素的顺序是否重要:

// take order into account
bool areEqual1 = Enumerable.SequenceEqual(list1, list2);

// ignore order
bool areEqual2 = !list1.Except(list2).Any() && !list2.Except(list1).Any();

我认为这是一个简单易行的方法来逐个元素比较两个列表

x=[1,2,3,5,4,8,7,11,12,45,96,25]
y=[2,4,5,6,8,7,88,9,6,55,44,23]

tmp = []


for i in range(len(x)) and range(len(y)):
    if x[i]>y[i]:
        tmp.append(1)
    else:
        tmp.append(0)
print(tmp)

使用除外:

var firstNotSecond = list1.Except(list2).ToList();
var secondNotFirst = list2.Except(list1).ToList();

我怀疑有一些方法实际上会比这个稍微快一点,但即使是这个方法也会比O(N * M)方法快得多。

如果你想把它们结合起来,你可以用上面的方法创建一个方法,然后创建一个return语句:

return !firstNotSecond.Any() && !secondNotFirst.Any();

需要注意的一点是,问题中的原始代码和这里的解决方案之间的结果存在差异:在我的代码中,只在一个列表中出现的任何重复元素将只报告一次,而在原始代码中出现的次数与它们相同。

例如,对于[1,2,2,2,3]和[1]的列表,原始代码中的“元素在list1但不是list2”结果将是[2,2,2,3]。在我的代码中,它就是[2,3]。在许多情况下,这不是一个问题,但这是值得注意的。

我已经使用这段代码来比较两个有百万记录的列表。

这种方法不会花很多时间

    //Method to compare two list of string
    private List<string> Contains(List<string> list1, List<string> list2)
    {
        List<string> result = new List<string>();

        result.AddRange(list1.Except(list2, StringComparer.OrdinalIgnoreCase));
        result.AddRange(list2.Except(list1, StringComparer.OrdinalIgnoreCase));

        return result;
    }