在linq中设置相等

时间:2009-06-03 14:37:53

标签: c# linq set equality

我有两个列表A和B(列表)。如何以最便宜的方式确定它们是否相等?我可以写一些类似'(A减B)联合(B减A)=空集'或将它们连接在一起并计算元素数量,但它相当昂贵。有解决方法吗?

5 个答案:

答案 0 :(得分:18)

如果列表项的排序是相关的:

bool areEqual = a.SequenceEqual(b);

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

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

SequenceEqual方法和HashSet<T>构造函数都具有带IEqualityComparer<T>参数的重载,如果您需要该功能。)

答案 1 :(得分:7)

嗯,这取决于你如何解释你的名单。

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

    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 :(得分:1)

这取决于你的意思“列表是平等的”。如果你的意思是它们包含相同的对象,Daniel建议的解决方案很好,只需要Union()两个列表并计算项目。

如果“相等”意味着他们有相同的项目以相同的顺序,那么您最好比较两个列表的计数,然后如果它们具有相同的计数,则只需使用普通for loop进行迭代,以比较同一索引处两个列表中的每个元素。不太好,但你很难快。

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:-1)

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

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

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

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

另一种解决方案 - 列表必须具有相同的长度和列表A减去列表B不得包含任何元素。

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