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

比较字典中的等式

  •  -3
  • BaltoStar  · 技术社区  · 7 年前

    如何最有效地比较两本字典以实现平等?--除了键的强制迭代外,尝试查找和比较值

    var d1 = new Dictionary<string,int>();
    d1.Add("a",2);
    d1.Add("b",1);
    d1.Add("c",1);
    
    var d2 = new Dictionary<string,int>();
    d2.Add("c",1);
    d2.Add("b",1);
    d2.Add("a",2);
    

    如何最有效地比较平等?

    不是这样的暴力:

    static bool CompareDictionaries(Dictionary<string,int> d1, Dictionary<string,int> d2)
    {
        if (d1.Count != d2.Count) return false;
        foreach(string key in d1.Keys)
        {
            if (!d2.ContainsKey(key)) return false;
            if (d1[key] != d2[key]) return false;
        }
        return true;
    }
    
    2 回复  |  直到 7 年前
        1
  •  -1
  •   Gauravsa    7 年前

    如果字典键相同,可以使用HashSet进行比较:

    var set1 = new HashSet<int>(dictionary1.Values);
    var set2 = new HashSet<int>(dictionary2.Values);
    

    然后可以使用Union、Intersect,除非由HashSet公开。此外,您还可以使用:

    bool isEqual = set1.SetEquals(set2);
    

    根据您的情况,基准测试是(HashSet vs Dictionary) here

        2
  •  -1
  •   Parrish Husband    7 年前

    加上习俗 SequenceEquals 扩展名,您可以指定如何比较键和值,如下所示:

    public static bool Equals<TKey, TValue>(IDictionary<TKey, TValue> a, IDictionary<TKey, TValue> b,
        IComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer)
    {
        if (ReferenceEquals(a, b))
            return true;
    
        if (b == null || a == null)
            return false;
    
        if (a.Count != b.Count)
            return false;
    
        var aOrdered = a.OrderBy(k => k.Key, keyComparer);
        var bOrdered = b.OrderBy(k => k.Key, keyComparer);
    
        return aOrdered.SequenceEqual(bOrdered, valueComparer);
    }
    

    分机:

    public static bool SequenceEqual<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> first, IEnumerable<KeyValuePair<TKey, TValue>> second, IEqualityComparer<TValue> valueComparer)
    {
        if (valueComparer == null) valueComparer = EqualityComparer<TValue>.Default;
        if (first == null) throw new ArgumentNullException(nameof(first));
        if (second == null) throw new ArgumentNullException(nameof(second));
    
        using (IEnumerator<KeyValuePair<TKey, TValue>> e1 = first.GetEnumerator())
        using (IEnumerator<KeyValuePair<TKey, TValue>> e2 = second.GetEnumerator())
        {
            while (e1.MoveNext())
            {
                if (!(e2.MoveNext() && valueComparer.Equals(e1.Current.Value, e2.Current.Value))) return false;
            }
            if (e2.MoveNext()) return false;
        }
        return true;
    }
    

    Dictionary<string,int> 例子:

    var areEqual = Equals(d1, d2, StringComparer.OrdinalIgnoreCase, EqualityComparer<int>.Default);