2010-10-13 39 views
35

Tôi muốn so sánh nội dung của hai trường hợp Dictionary<string, string> bất kể thứ tự của các mục mà chúng chứa. SequenceEquals cũng so sánh thứ tự, vì vậy đầu tiên tôi đặt hàng từ điển theo khóa và sau đó gọi SequenceEquals.So sánh 2 Từ điển <string, string> Instances

Có phương pháp nào tôi có thể sử dụng thay vì SequenceEquals sẽ chỉ so sánh nội dung không?

Nếu không có, đây có phải là cách lý tưởng để thực hiện việc này không?

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

Câu hỏi có chứa lỗ hổng rất lớn. Không có thứ gì như một thứ tự trong đó các phần tử có trong từ điển. Theo định nghĩa, một từ điển giữ chìa khóa để đánh giá các cặp mà không có bất kỳ thứ tự ngầm định nào. – Zordid

Trả lời

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

Bằng cách có từ điển không có thứ tự, thuật toán của bạn sẽ chạy trong O (n^2). –

+3

@Yuriy: Làm thế nào là nó O (n^2), giả sử rằng hashcodes là một nửa phong nha? – LukeH

+0

Giả sử GetHash được triển khai. –

6

Tôi không biết nếu có một phương pháp hiện nhưng bạn có thể sử dụng sau đây (kiểm tra null args bỏ qua cho ngắn gọn)

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

Nó sẽ là tốt nhất để thêm một quá tải để cho phép tùy chỉnh của EqualityComparer<TValue>.

0

này sẽ kiểm tra nếu tất cả Values từ source tồn tại trong target, bỏ qua Keys

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

Điều này bỏ lỡ trường hợp 'target' có cặp giá trị khóa bổ sung không có trong' source' – JaredPar

+0

@JaredPar: Nếu 'target' có bổ sung các cặp thì điều gì sẽ xảy ra? Trả về 'false' thay vì' true'? Sau đó, một kiểm tra bổ sung cho chiều dài sẽ sửa chữa nó phải không? – BrunoLM

+1

Tôi sẽ nói nếu nội dung khác nhau thì chúng không bằng nhau. Một kiểm tra chiều dài sẽ sửa 'target' là lớn hơn nhưng không phải là vấn đề của các phím khác nhau. – JaredPar

0

Nếu bạn sử dụng một SortedDictionary bạn sẽ không cần phải áp dụng việc phân loại chính mình, mà có thể là một chút dễ dàng hơn để sử dụng:

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!"); 
    } 
} 
Các vấn đề liên quan