比较 2 个 Dictionary<string, string> 实例

Posted

技术标签:

【中文标题】比较 2 个 Dictionary<string, string> 实例【英文标题】:Comparing 2 Dictionary<string, string> Instances 【发布时间】:2010-10-13 23:16:01 【问题描述】:

我想比较两个Dictionary&lt;string, string&gt; 实例的内容,而不管它们包含的项目的顺序如何。 SequenceEquals 也比较顺序,所以我先按键排序字典,然后调用SequenceEquals

有什么方法可以代替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));

【问题讨论】:

这个问题包含一个很大的缺陷。没有元素在字典中的顺序之类的东西。根据定义,字典保存键值对,没有任何隐式排序。 【参考方案1】:
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;

【讨论】:

通过无序字典,您的算法可以在 O(n^2) 中运行。 @Yuriy: O(n^2),假设哈希码是半体面的? 假设 GetHash 已实现。 我承认,我不知道 Object 上的 GetHashCode 实现返回了真实的哈希码。 @Yuriy:如果您使用字典,那么您要么 假设哈希码是一半,或者 你确保它们是.字典中的键查找被假定为大约 O(1)。如果不是,那么您将看到全面的性能不佳,而不仅仅是我的方法。【参考方案2】:

我不知道是否存在现有方法,但您可以使用以下方法(为简洁起见,省略了对 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&lt;TValue&gt;

【讨论】:

【参考方案3】:

如果您使用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!");
    

【讨论】:

【参考方案4】:

这将检查source中的所有Values是否存在于target中,忽略Keys

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

【讨论】:

这错过了target 具有不在source 中的附加键值对的情况 @JaredPar:如果target 有额外的配对,那么会发生什么?返回false 而不是true?然后额外检查长度会解决它吗? 我会说如果内容不同,那么它们就不相等。长度检查将解决 target 更大但不是密钥不同的问题。 @JaredPar:我假设 OP 只想比较内容。 [...] that will only compare the contents?

以上是关于比较 2 个 Dictionary<string, string> 实例的主要内容,如果未能解决你的问题,请参考以下文章

c# Dictionary拓展2个key得到1个value

C#中HashTable用法和Dictionary比较

在 C# 中枚举到字典

Dictionary和List遍历速度比较

算法问题实战策略 DICTIONARY

codeforces#766 D. Mahmoud and a Dictionary (并查集)