Linq在两个列表中找到差异

时间:2010-03-08 19:59:43

标签: linq set

我有两个这样的成员列表:

之前:彼得,肯,朱莉娅,汤姆

之后:彼得,罗伯特,朱莉娅,汤姆

正如你所看到的,肯已经出局,罗伯特也在。

我想要的是检测变化。我想要列出两个列表中已更改的内容。 linq如何帮助我?

4 个答案:

答案 0 :(得分:28)

您的问题尚未完全明确,但我认为您正在寻找差异(即排序无关紧要)。如果是这样,您需要两组中的symmetric difference。您可以使用Enumerable.Except

来实现此目的
before.Except(after).Union(after.Except(before));

答案 1 :(得分:21)

作为linq答案的替代方案,必须两次传递两个列表,请使用HashSet.SymmetricExceptWith()

var difference = new HashSet(before);
difference.SymmetricExceptWith(after);

可能效率更高。

答案 2 :(得分:5)

另一种方式:

before.Union(after).Except(before.Intersect(after))

答案 3 :(得分:2)

如果您的序列都是有序的,那么这是具有O(n)复杂度的版本:

    public static IEnumerable<T> SymmetricDifference<T>(IEnumerable<T> coll1, IEnumerable<T> coll2, IComparer<T> cmp)
    {
        using (IEnumerator<T> enum1 = coll1.GetEnumerator())
        using (IEnumerator<T> enum2 = coll2.GetEnumerator())
        {
            bool enum1valid = enum1.MoveNext();
            bool enum2valid = enum2.MoveNext();
            while (enum1valid && enum2valid)
            {
                int cmpResult = cmp.Compare(enum1.Current, enum2.Current);
                if (cmpResult < 0)
                {
                    yield return enum1.Current;
                    enum1valid = enum1.MoveNext();
                }
                else if (cmpResult > 0)
                {
                    yield return enum2.Current;
                    enum2valid = enum2.MoveNext();
                }
                else
                {
                    enum1valid = enum1.MoveNext();
                    enum2valid = enum2.MoveNext();
                }
            }
            while (enum1valid)
            {
                yield return enum1.Current;
                enum1valid = enum1.MoveNext();
            }
            while (enum2valid)
            {
                yield return enum2.Current;
                enum2valid = enum2.MoveNext();
            }
        }
    }


    public static IEnumerable<T> SymmetricDifference<T>(IEnumerable<T> coll1, IEnumerable<T> coll2)
    {
        return SymmetricDifference(coll1, coll2, Comparer<T>.Default);
    }