How to compare two Dictionaries in C#

2020-02-05 06:46发布

I have two Generic Dictionaries.Both have same keys.But values can be different.I want to compare 2nd dictionary with 1st dictionary .If there are differences between values i want to store those values in separate dictionary.

1st Dictionary
------------
key       Value

Barcode   1234566666
Price     20.00


2nd Dictionary
--------------
key       Value

Barcode   1234566666
Price     40.00


3rd Dictionary
--------------
key       Value

Price     40

Can Anyone give me a best algorithm to do this.I wrote an algorithm but it have lot of loops. I am seeking a short and efficient idea.Also like a solution by using LINQ query expression or LINQ lamda expression. I am using .Net Framework 3.5 with C#. I found some thing about Except() method. But Unfortunately i couldn't understand what is happening on that method. It is great if any one explains the suggested algorithm.

10条回答
我想做一个坏孩纸
2楼-- · 2020-02-05 07:11

You mentioned that both dictionaries have the same keys, so if this assumption is correct, you don't need anything fancy:

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

Or am I misunderstanding your problem?

查看更多
再贱就再见
3楼-- · 2020-02-05 07:13

Assuming both dictionaries have the same keys, the simplest way is

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

EDIT

Note that a.Except(b) gives a different result from b.Except(a):

a.Except(b): Price     20
b.Except(a): Price     40
查看更多
我命由我不由天
4楼-- · 2020-02-05 07:15

If you've already checked that the keys are the same, you can just use:

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

To explain, this will:

  • Iterate over the key/value pairs in dict2
  • For each entry, look up the value in dict1 and filter out any entries where the two values are the same
  • Form a dictionary from the remaining entries (i.e. the ones where the dict1 value is different) by taking the key and value from each pair just as they appear in dict2.

Note that this avoids relying on the equality of KeyValuePair<TKey, TValue> - it might be okay to rely on that, but personally I find this clearer. (It will also work when you're using a custom equality comparer for the dictionary keys - although you'd need to pass that to ToDictionary, too.)

查看更多
贼婆χ
5楼-- · 2020-02-05 07:15

converting the object to dictionary then following set concept subtract them, result items should be empty in case they are identically.

 public static IDictionary<string, object> 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<string, object> ToFlattenDictionary(this object source, string parentPropertyKey = null, IDictionary<string, object> parentPropertyValue = null)
    {
        var propsDic = parentPropertyValue ?? new Dictionary<string, object>();
        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.

source of the code

查看更多
登录 后发表回答