比较两个词典并回归差异

时间:2014-02-11 15:46:25

标签: c# dictionary compare where except

我有两个词典,一个包含原始数据,另一个包含新数据。我想比较两个词典并返回一个词典并返回包含更新的第三个词典。

Dictionary<int, Dictionary<string, string>> OriginalDictionary = new Dictionary
{
    {1, new Dictionary<string, string> 
        {{"name", "adam"}, 
         {"age", "15"}
         {"occupation", "student"}},
    {2, new Dictionary<string, string> 
        {{"name", "bob"}, 
         {"age", "40"}
         {"occupation", "doctor"}},
    {3, new Dictionary<string, string> 
        {{"name", "cameron"}, 
         {"age", "32"}
         {"occupation", "teacher"}},
}

Dictionary<int, Dictionary<string, string>> NewDictionary = new Dictionary
{
    {1, new Dictionary<string, string> 
        {{"name", "adam"}, 
         {"age", "15"}
         {"occupation", "student"}},
    {2, new Dictionary<string, string> 
        {{"name", "bob"}, 
         {"age", "40"}
         {"occupation", "lawyer"}}, //this is where it's different
    {3, new Dictionary<string, string> 
        {{"name", "cameron"}, 
         {"age", "32"}
         {"occupation", "teacher"}},
}

我想获得包含更新的第三个字典。它可以是整个第一级,也可以分为第二级。以下两个例子对我都有用。

Dictionary<int, Dictionary<string, string>> UpdateDictionary1 = new Dictionary
{
    {2, new Dictionary<string, string> 
        {{"name", "bob"}, 
         {"age", "40"}
         {"occupation", "lawyer"}} //this is where it's different
}

Dictionary<int, Dictionary<string, string>> UpdateDictionary2 = new Dictionary
{
    {2, new Dictionary<string, string> 
        {{"occupation", "lawyer"}}
}

我已经尝试过这篇文章How to compare two Dictionaries in C#的答案,但我为UpdateDictionary获得的结果仍然包含来自NewDictionary的所有数据。 UpdatesDictionary.Count == 3,我的预期输出应为UpdatesDictionary.Count == 1。我尝试了Where回答和Except回答,但他们都没有按照我的意愿行事。

UpdateDictionary = OriginalDictionary.Where(entry => NewDictionary[entry.Key] != entry.Value).ToDictionary(entry => entry.Key, entry => entry.Value);

UpdateDictionary = OriginalDictionary.Except(NewDictionary).ToDictionary(x => x.Key, x => x.Value);

还有其他方法可以解决这个问题吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

首先是简单的部分。找到已添加或删除的密钥:

var addedKeys = NewDictionary.Keys.Except(OriginalDictionary.Keys);
var removedKeys = OriginalDictionary.Keys.Except(NewDictionary.Keys);

接下来,要查找具有已编辑字典的键,我们将为字典创建一个相等比较器,只是因为尝试内联所有可能的方式可能会有所不同。

public class DictionaryComparer<TKey, TValue> :
    IEqualityComparer<Dictionary<TKey, TValue>>
{
    private IEqualityComparer<TValue> valueComparer;
    public DictionaryComparer(IEqualityComparer<TValue> valueComparer = null)
    {
        this.valueComparer = valueComparer ?? EqualityComparer<TValue>.Default;
    }
    public bool Equals(Dictionary<TKey, TValue> x, Dictionary<TKey, TValue> y)
    {
        if (x.Count != y.Count)
            return false;
        if (x.Keys.Except(y.Keys).Any())
            return false;
        if (y.Keys.Except(x.Keys).Any())
            return false;
        foreach (var pair in x)
            if (!valueComparer.Equals(pair.Value, y[pair.Key]))
                return false;
        return true;
    }

    public int GetHashCode(Dictionary<TKey, TValue> obj)
    {
        throw new NotImplementedException();
    }
}

现在我们有了这个,调用它非常简单:

var addedKeys = NewDictionary.Keys.Except(OriginalDictionary.Keys);
var removedKeys = OriginalDictionary.Keys.Except(NewDictionary.Keys);
var comparer = new DictionaryComparer<string, string>();
var editedValues = OriginalDictionary.Where(pair =>
    !comparer.Equals(pair.Value, NewDictionary[pair.Key]));