如何比较C#中的两个词典

我有两个Generic Dictionaries.Both有相同的键。但是值可以不同。我想比较第二个字典和第一个字典。如果值之间存在差异,我想将这些值存储在单独的字典中。

1st Dictionary ------------ key Value Barcode 1234566666 Price 20.00 2nd Dictionary -------------- key Value Barcode 1234566666 Price 40.00 3rd Dictionary -------------- key Value Price 40 

可以任何人给我一个最好的算法来做这个。我写了一个算法,但它有很多循环。我正在寻求一个简短而有效的想法。也像使用LINQ查询表达式或LINQ lamda表达式的解决方案。我正在使用。带有C#的Net Framework 3.5。 我发现了一些关于Except()方法的东西。但不幸的是我无法理解该方法发生了什么。如果有人解释建议的算法,那就太好了。我总是喜欢学习:)。

谢谢塔博。

如果您已经检查过密钥是否相同,您可以使用:

 var dict3 = dict2.Where(entry => dict1[entry.Key] != entry.Value) .ToDictionary(entry => entry.Key, entry => entry.Value); 

为了解释,这将:

  • 迭代dict2的键/值对
  • 对于每个条目,在dict1查找值并过滤掉两个值相同的任何条目
  • 从剩余的条目(即dict1值不同的条目)中形成字典,方法是从每对中获取密钥和值,就像它们在dict2出现dict2

请注意,这可以避免依赖于KeyValuePair的相等性 – 可以依赖它,但我个人觉得这更清楚。 (当你为字典键使用自定义相等比较器时它也会起作用 – 尽管你也需要将它传递给ToDictionary 。)

尝试:

 dictionary1.OrderBy(kvp => kvp.Key) .SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key)) 

你提到两个词典都有相同的键,所以如果这个假设是正确的,你不需要任何花哨的东西:

  foreach (var key in d1.Keys) { if (!d1[key].Equals(d2[key])) { d3.Add(key, d2[key]); } } 

或者我误解了你的问题?

检查任何差异,

 dic1.Count == dic2.Count && !dic1.Except(dic2).Any(); 

以下代码返回所有不同的值

 dic1.Except(dic2) 

您应该可以在键上加入它们并选择这两个值。 然后,您可以根据值是相同还是不同进行过滤。 最后,您可以使用键和第二个值将集合转换为字典。

  var compared = first.Join( second, f => f.Key, s => s.Key, (f,s) => new { f.Key, FirstValue = f.Value, SecondValue = s.Value } ) .Where( j => j.FirstValue != j.SecondValue ) .ToDictionary( j => j.Key, j => j.SecondValue ); 

使用循环也不应该太糟糕。 我怀疑它们会有类似的性能特征。

  var compared = new Dictionary(); foreach (var kv in first) { object secondValue; if (second.TryGetValue( kv.Key, out secondValue )) { if (!object.Equals( kv.Value, secondValue )) { compared.Add( kv.Key, secondValue ); } } } 

假设两个词典都具有相同的键,最简单的方法是

 var result = a.Except(b).ToDictionary(x => x.Key, x => x.Value); 

编辑

注意a.Except(b)给出与a.Except(b)不同的结果。 b.Except(a)

 a.Except(b): Price 20 b.Except(a): Price 40 
 var diff1 = d1.Except(d2); var diff2 = d2.Except(d1); return diff1.Concat(diff2); 

编辑:如果您确定所有键都相同,则可以执行以下操作:

 var diff = d2.Where(x=>x.Value != d1[x.Key]).ToDictionary(x=>x.Key, x=>x.Value); 

将对象转换为字典然后按照set概念减去它们,结果项应该为空,以防它们相同。

  public static IDictionary ToDictionary(this object source) { var fields = source.GetType().GetFields( BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance).ToDictionary ( propInfo => propInfo.Name, propInfo => propInfo.GetValue(source) ?? string.Empty ); var properties = source.GetType().GetProperties( BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance).ToDictionary ( propInfo => propInfo.Name, propInfo => propInfo.GetValue(source, null) ?? string.Empty ); return fields.Concat(properties).ToDictionary(key => key.Key, value => value.Value); ; } public static bool EqualsByValue(this object source, object destination) { var firstDic = source.ToFlattenDictionary(); var secondDic = destination.ToFlattenDictionary(); if (firstDic.Count != secondDic.Count) return false; if (firstDic.Keys.Except(secondDic.Keys).Any()) return false; if (secondDic.Keys.Except(firstDic.Keys).Any()) return false; return firstDic.All(pair => pair.Value.ToString().Equals(secondDic[pair.Key].ToString()) ); } public static bool IsAnonymousType(this object instance) { if (instance == null) return false; return instance.GetType().Namespace == null; } public static IDictionary ToFlattenDictionary(this object source, string parentPropertyKey = null, IDictionary parentPropertyValue = null) { var propsDic = parentPropertyValue ?? new Dictionary(); foreach (var item in source.ToDictionary()) { var key = string.IsNullOrEmpty(parentPropertyKey) ? item.Key : $"{parentPropertyKey}.{item.Key}"; if (item.Value.IsAnonymousType()) return item.Value.ToFlattenDictionary(key, propsDic); else propsDic.Add(key, item.Value); } return propsDic; } originalObj.EqualsByValue(messageBody); // will compare values. 

代码的来源