Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare 2 List<Dictionary<string, object>>

Tags:

c#

I have a function which returns a List<Dictionary<string, object>> where object is a standard type (string, int, etc).

I need to take a second List<Dictionary<string, object>> and ensure that All entries in list B are represented in List A (order in the list does not matter).

Currently I have code that looks like this:

foreach(Dictionary<string, object> rowResult in A) {
  foreach(Dictionary<string, object> rowCompare in B) {
    foreach(string columnName in rowResult.Keys) {
       // ... logic to compare columns
    }
  }

  // ...logic to compare rows so we dont find the same row twice.
}

Is there a more straightforward way to do this?

We dont care that all rows in rowResult are found, but all rows in rowCompare must be. It is ok to remove rows from the compare or result set to make the iteration easier.

My code works, it just looks over complicated and fragile.

like image 300
GrayWizardx Avatar asked Jan 22 '23 20:01

GrayWizardx


1 Answers

class DictionaryComparer<TKey, TValue> : IEqualityComparer<Dictionary<TKey, TValue>> {    
    public bool Equals(Dictionary<TKey, TValue> x, Dictionary<TKey, TValue> y) {
        if (x == null) {
            throw new ArgumentNullException("x");
        }
        if (y == null) {
            throw new ArgumentNullException("y");
        }
        if (x.Count != y.Count) {
            return false;
        }           
        foreach (var kvp in x) {
            TValue value;
            if(!y.TryGetValue(kvp.Key, out value)) {
                return false;
            }
            if(!kvp.Value.Equals(value)) {
                return false;
            }
        }
        return true;
    }

    public int GetHashCode(Dictionary<TKey, TValue> obj) {
        if (obj == null) {
            throw new ArgumentNullException("obj");
        }
        int hash = 0;
        foreach (var kvp in obj) {
            hash = hash ^ kvp.Key.GetHashCode() ^ kvp.Value.GetHashCode();
        }
        return hash;
    }
}

Then:

public bool Contains(
    List<Dictionary<string, object>> first,
    List<Dictionary<string, object>> second) {
    if(first == null) {
        throw new ArgumentNullException("first");
    }
    if(second == null) {
        throw new ArgumentNullException("second");
    }
    IEqualityComparer<Dictionary<string, object>> comparer = new DictionaryComparer<string, object>();
    return second.All(y => first.Contains(y, comparer));
}
like image 83
jason Avatar answered Jan 27 '23 14:01

jason