比较两个字典(键,值)并返回不具有相同值的键

Posted

技术标签:

【中文标题】比较两个字典(键,值)并返回不具有相同值的键【英文标题】: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” 【参考方案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!

【讨论】:

以上是关于比较两个字典(键,值)并返回不具有相同值的键的主要内容,如果未能解决你的问题,请参考以下文章

比较两个字典是不是相等

具有多个值的C#字典如何[重复]

将具有相同值的键相乘

使用具有多个值的键创建 NSDictionary

PySpark - 使用两个共享相同值的键创建对 RDD

Python字典相同值的键合并