【问题标题】:Compare two dictionaries (Dictionary<string, List<string>>)比较两个字典 (Dictionary<string, List<string>>)
【发布时间】:2014-12-03 02:06:14
【问题描述】:

我需要检查两个Dictionary&lt;string, List&lt;string&gt;&gt; 类型的字典是否相同。到目前为止,我有这个:

// 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 的值代表一个通用 List。

【问题讨论】:

  • 请问你为什么不接受我的回答?
  • 对不起。这是因为我仓促接受了,当我意识到字典键的变化被注册了,但是当我意识到你的比较看不到值的变化时,我不接受你的回答。
  • 列表中的值实际上是字符串还是任意对象?在第一种情况下,我的解决方案应该有效,否则您应该在每种可能的对象类型上实现 Equals(和 GetHashCode)。
  • 当然,这两个字典都包含纯字符串和字符串列表。相关类相当大,大约 900 行代码。我想我得再深入研究一下,看看是什么导致了这个问题。

标签: c# string dictionary compare


【解决方案1】:

未经测试,但我想以下方法可能有效:

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;

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

【讨论】:

  • 被接受,因为它也识别字符串的变化,所有其他方法都没有。谢谢!
  • +1 您可能应该添加一些长度检查,因为更长的 dictionary2/dictionary2 列表可以通过这些测试
  • @Alex K. 请问我会怎么做?我应该比较两个字典条目的总和吗?
  • 计数应该在循环之前,它不会改变!
  • @Richard 前一行检查密钥,如果不存在则返回 false。
【解决方案2】:

这是一个 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()))

如果你分发 not 然后你得到这个,请注意你必须将 ands (&amp;&amp;) 更改为 ors (||)。

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

另一种选择是将您的方法从DictionaryContentChanged 更改为DictionaryContentSame,并在需要时将其取反。

【讨论】:

  • 很棒的 Linq sn-p!但是您和 HimBromBeeres 的方法不会识别键(名称、计数)的值 List 中的任何变化。这可以通过添加到您的 sn-p 中来改变吗?
  • @betaFlux 我不明白你的意思。这将确保具有相同键的列表具有相同的值,而不管顺序如何。这不是你想要的吗?
  • 请再看看我的问题。我添加了一些信息。
  • @betaFlux 您在比较键 !synonymDictionary.Keys.Except(temporaryDictionary.Keys).Any() 的部分前面缺少一个非 !
  • @betaFlux 查看我对如何否定逻辑表达式的编辑。
【解决方案3】:

对两个词典进行排序并进行比较

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

【讨论】:

  • 这不起作用,因为它通过引用而不是内容来比较列表。
猜你喜欢
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-25
  • 2017-09-07
相关资源
最近更新 更多