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

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

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

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

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


当前回答

第一种方法:

if (list1 != null && list2 != null && list1.Select(x => list2.SingleOrDefault(y => y.propertyToCompare == x.propertyToCompare && y.anotherPropertyToCompare == x.anotherPropertyToCompare) != null).All(x => true))
   return true;

第二种方法,如果你对重复值没有问题:

if (list1 != null && list2 != null && list1.Select(x => list2.Any(y => y.propertyToCompare == x.propertyToCompare && y.anotherPropertyToCompare == x.anotherPropertyToCompare)).All(x => true))
   return true;

其他回答

试试这个方法:

var difList = list1.Where(a => !list2.Any(a1 => a1.id == a.id))
            .Union(list2.Where(a => !list1.Any(a1 => a1.id == a.id)));

更有效的方法是使用Enumerable。除了:

var inListButNotInList2 = list.Except(list2);
var inList2ButNotInList = list2.Except(list);

该方法是通过使用延迟执行实现的。这意味着你可以这样写:

var first10 = inListButNotInList2.Take(10);

它也很有效,因为它在内部使用Set<T>来比较对象。它的工作原理是首先从第二个序列中收集所有不同的值,然后将第一个序列的结果流式传输,检查它们是否之前没有出现过。

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();

不是针对这个问题,但是这里有一些代码来比较相等和不相等的列表!相同的对象:

public class EquatableList<T> : List<T>, IEquatable<EquatableList<T>> where    T : IEquatable<T>

/// <summary>
/// True, if this contains element with equal property-values
/// </summary>
/// <param name="element">element of Type T</param>
/// <returns>True, if this contains element</returns>
public new Boolean Contains(T element)
{
    return this.Any(t => t.Equals(element));
}

/// <summary>
/// True, if list is equal to this
/// </summary>
/// <param name="list">list</param>
/// <returns>True, if instance equals list</returns>
public Boolean Equals(EquatableList<T> list)
{
    if (list == null) return false;
    return this.All(list.Contains) && list.All(this.Contains);
}

也许这很有趣,但这对我来说很管用:

string.Join("",List1) != string.Join("", List2)