【问题标题】:Correct implementation of IEqualityComparer for List<Dictionary<string,string>>List<Dictionary<string,string>> 的 IEqualityComparer 的正确实现
【发布时间】:2016-08-11 13:55:53
【问题描述】:

我有两个 List&lt;Dictionary&lt;string,string&gt;&gt; 代表两个表。我想获取这些表中不同的 Dictionary 对象。

我正在尝试使用 except 方法,因为它基本上是做我想做的:它返回差异。但是因为此方法使用默认比较器,所以我创建了自己的 IEqualityComparer 实现。

在下面的示例中它工作得很好,但在现实生活中字典要复杂得多,所以我想知道 - 我的实现是一个好的解决方案还是必须增强?

class Program
{
    static void Main()
    {

        var table1 = new List<Dictionary<string, string>>{
        new Dictionary<string,string>{
        {"md5","0x1234"},
        {"file_name","name1234"},
        {"size","1234"}},

        new Dictionary<string,string>{
        {"md5","0x1234"},
        {"file_name","name1234"},
        {"size","1234"}},
        };

        var table2 = new List<Dictionary<string, string>>{
        new Dictionary<string,string>{
        {"md5","0x1234"},
        {"file_name","name1234"},
        {"size","1234"}},

        new Dictionary<string,string>{
        {"md5","0x5678"},
        {"file_name","name5678"},
        {"size","5678"}}
        };

        var diff = table2.Except(table1, new DictionaryComparer());

        foreach (var item in diff)
        {
            foreach (var value in item)
            {
                Console.WriteLine(value);
            }
            Console.WriteLine("+++++++++++++++++++++");
        }

        Console.ReadKey();
    }

    public class DictionaryComparer : IEqualityComparer<Dictionary<string, string>>
    {
        public bool Equals(Dictionary<string, string> first, Dictionary<string, string> second)
        {
            if (first == second) return true;
            if ((first == null) || (second == null)) return false;
            if (first.Count != second.Count) return false;

            foreach (var k in first.Keys)
                if (!second.ContainsKey(k))
                    return false;

            foreach (var k in first.Keys)
                if (!first[k].Equals(second[k]))
                    return false;

            return true;
        }

        public int GetHashCode(Dictionary<string, string> obj)
        {
            int resultValue = 0;

            if (obj == null)
            {
                return 0;
            }        

            foreach (var item in obj)
            {
                resultValue += (item.Key.Length + item.Value.Length);
            }

            return resultValue;
        }

    }

【问题讨论】:

  • 这不是哈希码的最佳实现,你应该谷歌 GetHashCode implementation 并阅读 stackoverflow 帖子
  • 嗯,听起来你可以去codereview.stackexchange.com
  • @CallumLinington 也许它的字典不会被存储在一个 hasset 或字典中并不那么重要?
  • 嗯,似乎如果有对象会有不同的 KVP,但这些 KVP 中的项目将具有相同的长度,我会为这些对象获得相同的哈希值,这不是很好,在谷歌搜索后更多我尝试过 foreach (var item in obj) { hash += (17 * item.Key.GetHashCode()) + item.Value.GetHashCode(); }

标签: c# .net dictionary


【解决方案1】:

我认为以下是更清洁的解决方案:

public class DictionaryComparer : IEqualityComparer<KeyValuePair<string, string>>
{
    public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
    {
        return x.Key.Equals(y.Key) 
            && x.Value.Equals(y.Value);
    }

    public int GetHashCode(KeyValuePair<string, string> obj)
    {
        return string.Concat(obj.Key, obj.Value)
            .GetHashCode();
    }
}

【讨论】:

  • GetHashCode() 中创建一个字符串对于一个应该非常精简且返回速度非常快的函数来说是一项相对昂贵的操作。
  • 嗯,我们如何比较字典中的值?
  • @sstan 我认为哈希生成的实现超出了这个问答范围,因此代码只是一个幼稚的例子。
  • 您可以访问 KeyValue 对,因此该对象使您可以访问两者。我更新了一个答案代码。
猜你喜欢
  • 1970-01-01
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
相关资源
最近更新 更多