比较两个字典(字典<字符串,列表>)

问题描述:

我需要检查Dictionary<string, List<string>>类型的两个字典是否相同。到目前为止,我有这样的:比较两个字典(字典<字符串,列表<string>>)

// dictionaries are already defined, so no parameters are required 
private bool DictionariesEqual() 
{ 
    return dictionary1.SequenceEqual(dictionary2); 
} 

我以为这只是检查键和值的顺序是一样的,这不是我想要的,因为的顺序并不重要,每个只有名称键和值

有没有办法检查不同字符串的字典,如果发现第一个不匹配,就返回false?

编辑

感谢您的帮助,但价值变动仍然无法识别。

更具体地讲,这里的功能(感谢@juharr),我如何使用它:

private bool DictionaryContentChanged() 
{ 
    if(synonymDictionary.Count != temporaryDictionary.Count || 
     synonymDictionary.Keys.Except(temporaryDictionary.Keys).Any() || 
     !synonymDictionary.Join(
      temporaryDictionary, 
      kvp => kvp.Key, 
      kvp => kvp.Key, 
      (kvp1, kvp2) => new 
      { 
       l1 = kvp1.Value, 
       l2 = kvp2.Value 
      }) 
      .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any())) 
      return true; 
     return false; 
{ 

我把它改成按一定的间隔反复检查更改的更新功能:

void Update(int interval) 
{ 
    while(!this.IsDisposed) 
    { 
     Set.Timer(interval); 

     if(DictionaryContentChanged()) 
     { 
      MessageBox.Show("Changes detected"); 
     } 
     else 
     { 
      // move on 
     } 
    } 
} 

当我添加,删除或更改值没有任何反应。消息框仅在密钥更改或key.Count更改时才显示。这可能与比较词典的功能有关吗?

请记住每个KeyValuePair的值代表一个通用列表。

+0

请问你为什么不排除我的答案? – HimBromBeere 2014-10-08 14:55:00

+0

对不起。这是因为我很快接受了它,当我意识到字典的关键变化已经被注册了,但是当我意识到价值变化没有被你的比较看到时,我就不接受你的答案。 – betaFlux 2014-10-08 15:16:03

+0

您的值是否在列表中实际上是字符串或任意对象?在第一种情况下,我的解决方案应该工作,否则您应该在每种可能类型的对象上实现Equals(和GetHashCode)。 – HimBromBeere 2014-10-09 06:05:57

排序两个字典,并比较其

bool result2 = dictionary1.OrderBy(r=>r.Key).SequenceEqual(dictionary2.OrderBy(r=>r.Key)); 
+0

这不起作用,因为它将引用列表与其内容进行比较。 – juharr 2014-10-08 13:22:14

没有测试,但我想下面可能工作:

if (dictionary1.Count != dictionary2.Count) return false; 
foreach (var kv in dictionary1) { 
    if (!dictionary2.ContainsKey(kv.Key) return false; 

    List list = dictionary2[kv.Key]; 
    if (!list.Count != dictionary1[kv.Key].Count) return false; 

    foreach(var value in kv.Value) { 
     if(!list.Contains(value)) return false; 
    } 
} 
return true; 

编辑:我加了一些长度检查。

+0

接受,因为它也识别字符串的变化,所有其他方法都没有。谢谢! – betaFlux 2014-10-08 12:17:45

+0

+1您应该添加一些长度检查,因为更长的dictionary2/dictionary2列表可以通过这些测试 – 2014-10-08 12:17:58

+0

@Alex K.我可以问我该怎么做?我应该比较两个字典的条目总数吗? – betaFlux 2014-10-08 12:21:32

这里有一个LINQ版本

dic1.Count == dic2.Count && 
!dic1.Keys.Except(dic2.Keys).Any() && 
dic1.Join(
    dic2, 
    kvp => kvp.Key, 
    kvp => kvp.Key, 
    (kvp1, kvp2) => new 
    { 
     l1 = kvp1.Value, 
     l2 = kvp2.Value 
    }) 
    .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any()) 

首先,它可以确保字典有相同数量的项目,那么它可以确保它们具有相同的密钥。然后它将它们连接到它们的键上,并确保具有相同键的所有列表具有相同的计数和相同的内容。

编辑

这里有一些方法来得到相对的回报值。

用()把整个东西包起来放一个!前面。

!(dic1.Count == dic2.Count && 
!dic1.Keys.Except(dic2.Keys).Any() && 
dic1.Join(
    dic2, 
    kvp => kvp.Key, 
    kvp => kvp.Key, 
    (kvp1, kvp2) => new 
    { 
     l1 = kvp1.Value, 
     l2 = kvp2.Value 
    }) 
    .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any())) 

如果你发布的不是,那么你得到这个,请注意,您必须将ANDS(&&)改为口服补液盐(||)。

dic1.Count != dic2.Count || 
dic1.Keys.Except(dic2.Keys).Any() || 
!dic1.Join(
    dic2, 
    kvp => kvp.Key, 
    kvp => kvp.Key, 
    (kvp1, kvp2) => new 
    { 
     l1 = kvp1.Value, 
     l2 = kvp2.Value 
    }) 
    .All(a => a.l1.Count == a.l2.Count && !a.l1.Except(a.l2).Any()) 

这是基于De Morgan's Law指出

Not(A And B) = Not A Or Not B 

另一种选择是改变你的方法从DictionaryContentChangedDictionaryContentSame,只是否定它,你使用它,如果需要的。

+0

棒极了Linq snippet!但是你和HimBromBeeres方法将不会识别键值(名称,计数)的值List 的任何更改。这可以通过你的代码片段的一小部分来改变吗? – betaFlux 2014-10-08 13:26:10

+0

@betaFlux我不明白你的意思。这将确保具有相同键的列表具有相同的值,而不管顺序如何。这不是你想要的吗? – juharr 2014-10-08 13:41:16

+0

请再看看我的问题。我添加了一些信息。 – betaFlux 2014-10-08 14:22:37