代码之家  ›  专栏  ›  技术社区  ›  Alsin

在LINQ中设置相等

  •  8
  • Alsin  · 技术社区  · 16 年前

    我有两个列表A和B(列表)。如何以最便宜的方式确定它们是否相等?我可以写一些类似“(a减去b)union(b减去a)=empty set”的东西,或者将它们连接在一起并计算元素的数量,但是它相当昂贵。有解决办法吗?

    5 回复  |  直到 10 年前
        1
  •  7
  •   Massimiliano    16 年前

    好吧,这取决于你如何解释你的清单。

    如果将它们视为元组(因此列表中元素的顺序很重要),那么可以使用以下代码:

        public bool AreEqual<T>(IList<T> A, IList<T> B)
        {
            if (A.Count != B.Count)
                return false;
            for (int i = 0; i < A.Count; i++)
                if (!A[i].Equals(B[i])) 
                    return false;
        }
    

    如果您将列表视为集合(因此元素的顺序无关紧要),那么…我想您使用的数据结构是错误的:

        public bool AreEqual<T>(IList<T> A, IList<T> B)
        {
            HashSet<T> setA = new HashSet<T>(A);
            return setA.SetEquals(B);
        }
    
        2
  •  18
  •   LukeH    10 年前

    如果列表项的顺序相关:

    bool areEqual = a.SequenceEqual(b);
    

    如果要将列表视为无序集:

    // assumes that the list items are ints
    bool areEqual = new HashSet<int>(a).SetEquals(b);
    

    (The SequenceEqual 方法与 HashSet<T> 构造函数都具有采用 IEqualityComparer<T> 参数,如果需要该功能。)

        3
  •  1
  •   Yann Schwartz    16 年前

    这取决于你所说的“清单是平等的”。如果您的意思是它们包含相同的对象,那么丹尼尔建议的解决方案是好的,只需union()这两个列表并对项目进行计数。

    如果“相等”,则表示它们具有相同的项。 按同样的顺序 ,您最好比较两个列表的计数,然后如果它们具有相同的计数,只需使用一个普通的 for loop 在同一索引处比较两个列表中的每个元素。不那么漂亮,但你几乎快不了。

        4
  •  1
  •   mqp    16 年前

    这里没有快捷方式,除非对列表进行排序,在这种情况下,您可以逐个比较元素。显然,我认为顺序无关紧要,否则很明显,你也可以一个接一个地比较它们。

    否则,我建议对于大的项目列表,您可以得到的最有效的算法可能是这样的,使用哈希表跟踪您看到的内容(警告:尚未测试,但应该很清楚我在获取什么)。

    public static bool IsEqual<T>(this List<T> x1, List<T> x2)
    {
        if(x1.Count != x2.Count) return false;
    
        var x1Elements = new Dictionary<T, int>();
    
        foreach(var item in x1)
        {
            int n; x1Elements.TryGetValue(item, out n);
            x1Elements[item] = n+1;
        }
    
        foreach(var item in x2)
        {
            int n; x1Elements.TryGetValue(item, out n);
            if(n <= 0) return false; // this element was in x2 but not x1
            else x1Elements[item] = n-1;
        }
    
        // make sure x1 didn't have any elements
        // that weren't in x2
    
        return x1Elements.Values.All(x => x == 0);
    }
    
        5
  •  -1
  •   Daniel Brückner    16 年前

    第一个快照-如果它们包含相同的项,则两个列表的并集应具有与两个列表中任何一个相同的项数。

    listA.Union(listB).Count() == listA.Count()
    

    注意:如果一个列表为空,则失败。

    但它可能仍然是一个 O(n²) 操作。

    另一个解决方案-列表的长度必须相同,列表A减去列表B不能包含任何元素。

    (listA.Count() == listB.Count()) && !listA.Except(listB).Any()