【问题标题】:Linq find differences in two listsLinq 在两个列表中查找差异
【发布时间】:2011-01-25 03:32:23
【问题描述】:

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

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

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

如您所见,Ken 出局,Robert 入局。

我想要的是检测变化。我想要两个列表中发生变化的列表。 linq 对我有什么帮助?

【问题讨论】:

  • 我认为你需要多定义一点“改变”。例如,项目顺序的改变对你来说是“改变”吗?

标签: linq set


【解决方案1】:

这是具有 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);
    }

【讨论】:

  • 这仅适用于已排序的序列,对吧?对于任意序列,不能仅在 O(n) 中生成 symdiff。
  • 确实如此,看看协同迭代。它是来自合并排序的顺序合并的略微修改版本。虽然它不适用于未排序,但它对于已排序非常高效,因此在许多情况下,对集合进行预排序然后使用此过滤器会更快且更节省内存~> n + 2*(n log n) 而不是一些天真的 all-vs-all n^2 或一些哈希表内存猪..当然是在 许多 元素的情况下:)
【解决方案2】:

您的问题没有完全指定,但我假设您正在寻找集合中的差异(也就是说,排序无关紧要)。如果是这样,您需要两组中的symmetric difference。您可以使用Enumerable.Except 实现此目的:

before.Except(after).Union(after.Except(before));

【讨论】:

    【解决方案3】:

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

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

    可能会更有效率。

    【讨论】:

      【解决方案4】:

      另一种方式:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-04
        • 1970-01-01
        • 1970-01-01
        • 2015-03-19
        • 2010-09-19
        相关资源
        最近更新 更多