如何比较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.
代码的来源