比较2 List <dictionary <string,object =“”>&gt; </dictionary <string,>

时间:2009-12-18 02:08:05

标签: c#

我有一个返回List<Dictionary<string, object>>的函数,其中object是标准类型(string,int等)。

我需要花一秒List<Dictionary<string, object>>并确保列表B中的所有条目都在列表A中表示(列表中的顺序无关紧要)。

目前我的代码如下所示:

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

有更简单的方法吗?

我们不关心rowResult中的所有行,但rowCompare中的所有行都必须是。 可以从比较或结果集中删除行,以使迭代更容易。

我的代码有效,它只是看起来过于复杂和脆弱。

3 个答案:

答案 0 :(得分:6)

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

然后:

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

答案 1 :(得分:2)

嗯......你在做什么 for ?我问的原因是这个超级有用的单元测试方法称为CollectionAssert.AreEquivalent

来自备注部分:

  

如果两个集合具有相同数量的相同元素,则它们是等效的,但是以任何顺序排列。如果元素的值相等,则元素相等,而不是它们引用相同的对象。

看起来它完全符合您的要求,如果两者不相等,则抛出AssertFailedException,这也可能是您想要的。有没有办法利用它?一个方法调用肯定远远大于三重嵌套循环 - 即使这是方法所做的事情。

答案 2 :(得分:1)

foreach(Dictionary<string, object> rowCompare in B)
    if(!A.Contains(rowCompare)) return false;
return true;

假设您的比较器设置得当,这将有效。并且简单易懂。如果你发现它更容易,你甚至可以重新添加大括号。