【问题标题】:Comparing two dictionaries (Key, value) and return Keys that doesn't have same value比较两个字典(键,值)并返回不具有相同值的键
【发布时间】:2022-01-18 15:17:23
【问题描述】:

我对 c# 有点陌生,想在比较两个字典时识别不具有相同值的键。

我的字典是 dict => KeyValuePair。我有两本字典,比如 -

dict1 => {"a":"False","b":"amazonaws.com","c":"True"}
dict2 => {"a":"True","b":"amazonaws.com","c":"False"}

我想比较两个字典并返回一个变量,该变量将具有 Keys ["a", "c"] 就像上面的示例一样,这些键具有不同的值。

目前我编写的逻辑只会区分其他字典中不存在的键。

Dictionary dictExcept = null;
foreach (IDictionary kvp in dict1.Cast<object>().Where(kvp => !dict2.Contains(kvp)))
    {
        dictExcept.Add(kvp.Keys, kvp.Values);
    }
return dictExcept ;

【问题讨论】:

  • 循环通过 dict1.Keys 并为每个键检查 if(dict1[key] != dict2[key]) keyList.Add(key); keyList 是否是 List&lt;string&gt; 假设两个字典中的键都是字符串类型。
  • 我们可以假设两个字典包含完全相同的键(或者你只对那些感兴趣)吗?或者您是否还试图解释存在于一个中但不存在于另一个中的密钥?
  • @Flater 两个字典都有相同的键,只是我们需要识别具有不同值的键
  • 不要忘记实例化dictExcept,因为这会抛出异常:“dictExcept.Add”

标签: c# .net dictionary


【解决方案1】:

你可以试试TryGetValue:

using System.Linq;

...

var dictExcept = dict1
  .Where(pair => dict2.TryGetValue(pair.Key, out var value) && 
                 pair.Value != value)
  .ToDictionary(pair => pair.Key, 
                pair => (first: pair.Value, second: dict2[pair.Key]));

这里我们针对dict1中的每个键值pair尝试从dict2获取对应的value

// dict2 has pair.Key it corresponds to value...
dict2.TryGetValue(pair.Key, out var value) && 
// however value from dict2 != value from dict1
pair.Value != value

如果您更喜欢使用 foreach(没有 Linq 解决方案),那么同样的想法:

var dictExcept = new Dictionary<string, (string first, string second)>();

foreach (var pair in dict1)
  if (dict2.TryGetValue(pair.Key, out var value) && value != pair.Value)
    dictExcept.Add(pair.Key, (pair.Value, value)); 

演示: (fiddle)

  var dict1 = new Dictionary<string, string> { 
    { "a", "False" }, { "b", "False" }, { "c", "True" }, { "d", "dict1 only" } };

  var dict2 = new Dictionary<string, string> { 
    { "a", "False" }, { "b", "True" }, { "c", "False" }, { "e", "dict2 only" } };

  var dictExcept = dict1
    .Where(pair => dict2.TryGetValue(pair.Key, out var value) &&
                   pair.Value != value)
    .ToDictionary(pair => pair.Key,
                  pair => (first: pair.Value, second: dict2[pair.Key]));

  string report = string.Join(Environment.NewLine, dictExcept
    .Select(pair => $"Key: {pair.Key}; Values: {pair.Value}"));

  Console.Write(report);

结果:

Key: b; Values: (False, True)
Key: c; Values: (True, False)

【讨论】:

    【解决方案2】:

    根据您的评论提供最简单的答案:

    两个字典都有相同的键,只是我们需要识别具有不同值的键

    在您不需要考虑丢失键的假设下工作,您可以简单地遍历其中一个字典的所有键,并比较在该键下找到的值。

    var keysWithDifferentValues = new List<string>();
    
    foreach (var kvp in dict1)
    {
        if(!kvp.Value.Equals(dict2[kvp.Key]))
            keysWithDifferentValues.Add(kvp.Key);
    }
    

    这可以使用 LINQ 来简化:

    var keysWithDifferentValues = 
          dict1
            .Where(kvp => !kvp.Value.Equals(dict2[kvp.Key]))  
            .Select(kvp => kvp.Key)
            .ToList();                                  
    

    【讨论】:

      【解决方案3】:

      既然您有一本名为dictExcept 的字典,那么使用Expect 为您完成这项工作怎么样?

      产生两个序列的集合差。

      source

      在你的情况下:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      
      public class Program
      {
          static void Main(string[] args)
          {
              var a = new Dictionary<string, string>{{"a", "False"}, {"b", "False"}, {"c", "True"}};
              var b = new Dictionary<string, string>{{"a", "False"}, {"b", "True"}, {"c", "False"}};
              
              var c = a.Except(b).Select(x => x.Key);
              c.Dump();
          }
      }
      

      输出

      [ b, c ]
      

      Try it online!

      更多不同案例的例子:

      static void Main(string[] args)
      {
          var a = new Dictionary<string, string>{{"a", "False"}, {"b", "False"}, {"c", "True"}};
          var b = new Dictionary<string, string>{{"a", "False"}, {"b", "True"}, {"c", "False"}};
          
          var c = a.Except(b).Select(x => x.Key);
          // c is [ b ,c ]
          
          a.Add("d", "foo");
          
          var d = a.Except(b).Select(x => x.Key);
          // d is [ b, c, d ]
          
          b.Add("e", "foo");
          
          var e = a.Except(b).Select(x => x.Key);
          // e is still [ b, c, d ]
          
          var e2 = (a.Except(b)).Union(b.Except(a)).Select(x => x.Key).Distinct();
          // e is [ b, c, d, e ]
      }
      

      Try it Online!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多