2010-10-13 123 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!"); 
    } 
} 
相關問題