【问题标题】:SortedDictionary<TKey, TValue>: check if contents equal to another SortedDictionary?SortedDictionary<TKey, TValue>:检查内容是否等于另一个 SortedDictionary?
【发布时间】:2018-03-22 04:19:39
【问题描述】:

只是想知道:如果我有两个 SortedDictionary 对象,找出它们的内容是否相同的最快方法是什么? 循环所有键并检查值听起来不是最好的解决方案。 只检查 GetHashCode() 就足够了吗?

编辑:我已经尝试了一下。请参阅此代码:

SortedDictionary<string, string> o1 = new SortedDictionary<string, string>( );
SortedDictionary<string, string> o2 = new SortedDictionary<string, string>( );
o1["k1"] = "v1";
o1["k2"] = "v2";
o1["k3"] = "v3";

o2["k2"] = "v2";
o2["k1"] = "v1";
o2["k3"] = "v3";

Console.WriteLine( "o1:" );
foreach ( KeyValuePair<string, string> oKeyValuePair in o1 )
{
    Console.WriteLine( oKeyValuePair.GetHashCode( ) );
}
Console.WriteLine( "o2:" );
foreach ( KeyValuePair<string, string> oKeyValuePair in o2 )
{
    Console.WriteLine( oKeyValuePair.GetHashCode( ) );
}
Console.ReadKey( );

各个键值对的哈希码对于两个已排序的字典都是相同的,即使添加值的顺序不同。这很好。 所以我错过了一步:如何从所有哈希码中获取一个唯一的哈希码?

【问题讨论】:

    标签: c#


    【解决方案1】:

    不,检查 GetHashCode 是不够的,即使 SortedDictionary&lt;,&gt; 覆盖它 - 我不相信它会这样做。

    据我所知,您确实必须循环检查所有键和值。从根本上说,任何解决方案都必须这样做。您还应该检查所涉及的比较函数是否相同...否则字典并不真正等效。

    【讨论】:

      【解决方案2】:

      您必须准备好遍历所有这些,但您可以先测试一些重要的捷径。

      第一个捷径,是检查对象身份。虽然“A is A”并不像 Ayn Rand 想象的那么深刻,但它是一种让相等代码更快的便捷方法。身份总是需要相等,并且在实际代码中很常见的是最终将某物与自身进行比较(尤其是在集合查找、循环以及对象通过多层代码传递的地方)。

      另外一个就是内容相同,大小不能不同,获取大小很快。

      因此,您可以获得的最快速度是:

      public static bool EqualSortedDict<K, V>(SortedDictionary<K, V> x, SortedDictionary<K, V> y)
      {
        if(ReferenceEquals(x, y))
          return true;
        if(ReferenceEquals(x, null) || ReferenceEquals(y, null))
          return false; //both being null already hit above.
        if(x.Count != y.Count)
          return false;
        if(!x.Comparer.Equals(y.Comparer))
          return false;//check if this is what you need. Probably is but might
                       //not be in some cases.
        foreach(KeyValuePair<K, V> kvp in x)
        {
          V cmpValue = default(V);
          if(!y.TryGetValue(kvp.Key, out cmpValue) || !kvp.Value.Equals(cmpValue))
            return false;
        }
        return true;
      }
      

      请注意,GetHashCode() 在上面不起作用的原因是,SortedDictionary 上 GetHashCode() 的默认实现仅适用于对象标识。如果您需要一个基于值的 GetHashCode()(如果您的 SortedDictionary 本身就是一个键或放置在一个 HashSet 中),那么您将必须实现一个 IEqualityComparer 来生成适当的哈希码。即使这样,它也可能需要很长时间来计算自己(它可能总是循环遍历所有项目来做你想做的事),而 a.GetHashCode() != b.GetHashCode() 证明 a != b (对于hashcode 支持的相等定义),a.GetHashCode() == b.GetHashCode() 并不能证明 a == b,因为会有冲突。

      【讨论】:

      • 听起来很合理,我最终使用了类似的实现。事实证明,键值对的哈希值可能会改变。谢谢。
      • @Krumelur。实际上,现在只看这个,因为 kvp 顺序是使用排序的 dict 排序的,所以在每个 MoveNext 之后抓取两个枚举器并比较 Current 仍然更快。只要您不想考虑具有不同比较器等效的字典(在这种情况下,排序顺序将不同并且这种加速将不起作用),这会将第二个字典中相关值的每次搜索减少到 O( 1)。我想得更笼统(以上是基于哈希的字典或其他不保持排序顺序的唯一方法)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 2011-06-05
      • 1970-01-01
      • 2010-11-11
      • 2010-12-31
      相关资源
      最近更新 更多