2010-10-13 98 views
35

我想比较两个Dictionary<string, string>实例的内容,而不管它们包含的项目的顺序如何。 SequenceEquals也比较了顺序,所以我先通过键命令字典,然后拨打SequenceEquals比较2字典<字符串,字符串>实例

有没有一种方法可以用来代替SequenceEquals,它只会比较内容?

如果没有,这是做这件事的理想方式吗?

Dictionary<string, string> source = new Dictionary<string, string>(); 
Dictionary<string, string> target = new Dictionary<string, string>(); 

source["foo"] = "bar"; 
source["baz"] = "zed"; 
source["blah"] = null; 

target["baz"] = "zed"; 
target["blah"] = null; 
target["foo"] = "bar"; 

// sequenceEquals will be false 
var sequenceEqual = source.SequenceEqual(target); 
// contentsEqual will be true 
var contentsEqual = source.OrderBy(x => x.Key).SequenceEqual(target.OrderBy(x => x.Key)); 
+0

这个问题包含一个很大的缺陷。没有任何元素在字典中的顺序。根据定义,字典包含没有任何隐式排序的值对的关键字。 – Zordid 2017-11-10 14:58:03

回答

52
var contentsEqual = source.DictionaryEqual(target); 

// ... 

public static bool DictionaryEqual<TKey, TValue>(
    this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second) 
{ 
    return first.DictionaryEqual(second, null); 
} 

public static bool DictionaryEqual<TKey, TValue>(
    this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second, 
    IEqualityComparer<TValue> valueComparer) 
{ 
    if (first == second) return true; 
    if ((first == null) || (second == null)) return false; 
    if (first.Count != second.Count) return false; 

    valueComparer = valueComparer ?? EqualityComparer<TValue>.Default; 

    foreach (var kvp in first) 
    { 
     TValue secondValue; 
     if (!second.TryGetValue(kvp.Key, out secondValue)) return false; 
     if (!valueComparer.Equals(kvp.Value, secondValue)) return false; 
    } 
    return true; 
} 
+0

通过使用无序字典,您的算法在O(n^2)中运行。 – 2010-10-13 23:26:27

+3

@Yuriy:它是怎么样的O(n^2),假设哈希码是一半体面的? – LukeH 2010-10-13 23:28:09

+0

假设GetHash已实施。 – 2010-10-13 23:29:25

6

我不知道是否有一个现有的方法,但你可以使用以下(略去了空args来检查)

public static bool DictionaryEquals<TKey,TValue>(
    this Dictionary<TKey,TValue> left, 
    Dictionary<TKey,TValue> right) { 

    var comp = EqualityComparer<TValue>.Default; 
    if (left.Count != right.Count) { 
    return false; 
    } 
    foreach (var pair in left) { 
    TValue value; 
    if (!right.TryGetValue(pair.Key, out value) 
     || !comp.Equals(pair.Value, value)) { 
     return false; 
    } 
    } 
    return true; 
} 

这将是最好添加一个超载以允许定制EqualityComparer<TValue>

0

这将检查是否从source所有Values存在target,忽略了Keys

var result = source.All(x => target.Any(y => x.Value == y.Value)); 
+4

这错过了'目标'具有额外的键值对不在'源'的情况下 – JaredPar 2010-10-13 23:28:37

+0

@JaredPar:如果'target'有额外的双然后会发生什么?返回'false'而不是'true'?那么额外的长度检查将修复它的权利? – BrunoLM 2010-10-13 23:34:22

+1

我会说,如果内容不同,那么他们是不相等的。长度检查会修复“目标”更大,但不是密钥不同的问题。 – JaredPar 2010-10-13 23:41:33

0

如果使用SortedDictionary你不会需要应用自己的排序,可以是更加容易的使用方法:

void Main() 
{ 
    var d1 = new Dictionary<string, string> 
    { 
     ["a"] = "Hi there!", 
     ["b"] = "asd", 
     ["c"] = "def" 
    }; 
    var d2 = new Dictionary<string, string> 
    { 
     ["b"] = "asd", 
     ["a"] = "Hi there!", 
     ["c"] = "def" 
    }; 

    var sortedDictionary1 = new SortedDictionary<string, string>(d1); 
    var sortedDictionary2 = new SortedDictionary<string, string>(d2); 

    if (sortedDictionary1.SequenceEqual(sortedDictionary2)) 
    { 
     Console.WriteLine("Match!"); 
    } 
    else 
    { 
     Console.WriteLine("Not match!"); 
    } 
} 
相关问题