Compare two dictionaries (dictionary <string, list <string >>)

I need to check if two type dictionaries are identical Dictionary<string, List<string>>

. So far I have this:

// dictionaries are already defined, so no parameters are required
private bool DictionariesEqual()
{
   return dictionary1.SequenceEqual(dictionary2);
}

      

I assume this only checks if the order of the keys and values ​​is the same, which I don't want because the order doesn't matter, just the name of each key and value .

Is there a way to check dictionaries for unequal strings and return false if the first mismatch is found?

EDIT

Thanks for your help, but value changes are still not recognized.

To be more specific, here's the function (thanks @juharr) and how I use it:

private bool DictionaryContentChanged()
{
    if(synonymDictionary.Count != temporaryDictionary.Count ||
       synonymDictionary.Keys.Except(temporaryDictionary.Keys).Any() ||
       !synonymDictionary.Join(
            temporaryDictionary,
            kvp => kvp.Key,
            kvp => kvp.Key,
            (kvp1, kvp2) => new
            {
                l1 = kvp1.Value,
                l2 = kvp2.Value
            })
            .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any()))
            return true;
        return false;
{

      

I put it in an update function that checks for changes multiple times at a specific interval:

void Update(int interval)
{
    while(!this.IsDisposed)
    {
        Set.Timer(interval);

        if(DictionaryContentChanged())
        {
            MessageBox.Show("Changes detected");
        }
        else
        {
            // move on
        }
    }
}

      

When I add, remove or change the value, nothing happens. The message field appears only in case of key change or key change. Could it be related to a function that compares dictionaries?

Remember that the value of each KeyValuePair represents a generic list.

+3


source share


3 answers


Untested, but I think the following might work:

if (dictionary1.Count != dictionary2.Count) return false;
foreach (var kv in dictionary1) {
    if (!dictionary2.ContainsKey(kv.Key) return false;

    List list = dictionary2[kv.Key];
    if (!list.Count != dictionary1[kv.Key].Count) return false;

    foreach(var value in kv.Value) {
        if(!list.Contains(value)) return false;
    }
}
return true;

      



EDIT: I've added some length checks.

+3


source


Here's the Linq version

dic1.Count == dic2.Count &&
!dic1.Keys.Except(dic2.Keys).Any() &&
dic1.Join(
    dic2,
    kvp => kvp.Key,
    kvp => kvp.Key,
    (kvp1, kvp2) => new
    {
        l1 = kvp1.Value,
        l2 = kvp2.Value
    })
    .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any())

      

Make sure the dictionaries have the same cardinality first and then make sure they have the same keys. He then attaches to them on his keys and makes sure that all lists with the same keys have the same number and the same content.

Edit

There are several ways to get the inverse return value.

Wrap everything with () and put it down! in front.



!(dic1.Count == dic2.Count &&
!dic1.Keys.Except(dic2.Keys).Any() &&
dic1.Join(
    dic2,
    kvp => kvp.Key,
    kvp => kvp.Key,
    (kvp1, kvp2) => new
    {
        l1 = kvp1.Value,
        l2 = kvp2.Value
    })
    .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any()))

      

If you distribute the wrong thing, you get this, note that you need to change ands ( &&

) to ors ( ||

).

dic1.Count != dic2.Count ||
dic1.Keys.Except(dic2.Keys).Any() ||
!dic1.Join(
    dic2,
    kvp => kvp.Key,
    kvp => kvp.Key,
    (kvp1, kvp2) => new
    {
        l1 = kvp1.Value,
        l2 = kvp2.Value
    })
    .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any())

      

This is based on De Morgan Law , which states that

Not(A And B) = Not A Or Not B

      

Another option is to change the method from DictionaryContentChanged

to DictionaryContentSame

and just undo it if you use it, if necessary.

+1


source


Sort dictionaries and compare them

bool result2 = dictionary1.OrderBy(r=>r.Key).SequenceEqual(dictionary2.OrderBy(r=>r.Key));

      

-1


source







All Articles