-3

How to most efficiently compare two Dictionary for equality ? -- other than brute force iteration of keys, try lookup, and comparing values

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

How to most efficiently compare for equality ?

Not brute force like this :

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;
}
Parrish Husband
  • 3,148
  • 18
  • 40
BaltoStar
  • 8,165
  • 17
  • 59
  • 91
  • 2
    What do you want to occur if one of the dictionaries is case sensitive and the other isn't? Your existing code won't 'work' in that scenario (e.g. it will say some dictionaries are the same when they really aren't) - I am just checking if that is on purpose or not. – mjwills Sep 02 '18 at 23:29
  • 1
    Possible duplicate of [How to compare two Dictionaries in C#](https://stackoverflow.com/questions/9547351/how-to-compare-two-dictionaries-in-c-sharp) (specifically https://stackoverflow.com/a/9547410/34092) – mjwills Sep 02 '18 at 23:30
  • @mjwills you'd have to pass in the comparers right? – Parrish Husband Sep 03 '18 at 00:31
  • @ParrishHusband It depends what the OP wants. It is **most likely** they want https://stackoverflow.com/a/9547410/34092 . – mjwills Sep 03 '18 at 00:35
  • @baltostar: is there an assumption dictionaries contain identical keys – Gauravsa Sep 03 '18 at 00:49
  • Is there a reason traditional key/value approach isn't viable here? Knowing more might help come up with an alternate approach. – Parrish Husband Sep 03 '18 at 01:40

2 Answers2

-1

Coupled with a custom SequenceEquals extension, you can specify how you'll be comparing keys and values with something like this:

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

Extension:

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

Which you could call in OP's specific Dictionary<string,int> example:

var areEqual = Equals(d1, d2, StringComparer.OrdinalIgnoreCase, EqualityComparer<int>.Default);
Parrish Husband
  • 3,148
  • 18
  • 40
-1

If the Dictionary keys are same, you can use HashSet to compare:

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

Then can use Union, Intersect, Except exposed by HashSet. Also, you can use this:

bool isEqual = set1.SetEquals(set2);

Depending upon your situation, benchmarking is (HashSet vs Dictionary) here

Gauravsa
  • 6,330
  • 2
  • 21
  • 30