为两个订单 ID 的排列创建唯一的哈希码

本文关键字:ID 排列 创建 哈希码 唯一 两个 | 更新日期: 2023-09-27 18:23:56

我有一个集合,它是两个唯一订单的排列,其中 OrderId 是唯一的。因此,它包含Order1 (Id = 1)Order2 (Id = 2),既1221。现在,在处理路由算法时,检查的条件很少,当组合包含在最终结果中时,必须忽略其反向,并且无需考虑进行处理。现在,由于 Id 是一个整数,我创建了一个以下逻辑:

 private static int GetPairKey(int firstOrderId, int secondOrderId)
        {
            var orderCombinationType = (firstOrderId < secondOrderId)
                ? new {max = secondOrderId, min = firstOrderId}
                : new { max = firstOrderId, min = secondOrderId };
            return (orderCombinationType.min.GetHashCode() ^ orderCombinationType.max.GetHashCode());
        }

在逻辑中,我创建了一个Dictionary<int,int>,其中键是使用上面显示的方法创建的GetPairKey其中我确保在给定的组合中正确排列它们,以便我得到相同的哈希码,可以插入并检查字典中的条目,而它的值是虚拟的,它被忽略了。

但是上面的逻辑似乎有一个缺陷,它不能像预期的那样对所有逻辑处理工作,在这种情况下我做错了什么,我应该尝试一些不同的东西来创建Hashcode.像下面的代码是更好的选择,请建议

Tuple.Create(minOrderId,maxOrderId).GetHashCode,以下是相关的代码用法:

  foreach (var pair in localSavingPairs)
            {
                    var firstOrder = pair.FirstOrder;
                    var secondOrder = pair.SecondOrder;
                   if (processedOrderDictionary.ContainsKey(GetPairKey(firstOrder.Id, secondOrder.Id))) continue;

添加到字典的是以下代码:

processedOrderDictionary.Add(GetPairKey(firstOrder.Id, secondOrder.Id), 0);这里的值 0 是虚拟的,没有使用

为两个订单 ID 的排列创建唯一的哈希码

您需要一个可以唯一表示每个可能值的值。

这与哈希代码不同。

您可以使用long或包含所有适当值的类或结构唯一地表示每个值。由于在一定总大小之后使用 long 将不再起作用,让我们看看另一种方法,它更灵活、更可扩展:

public class KeyPair : IEquatable<KeyPair>
{
  public int Min { get; private set; }
  public int Max { get; private set; }
  public KeyPair(int first, int second)
  {
    if (first < second)
    {
      Min = first;
      Max = second;
    }
    else
    {
      Min = second;
      Max = first;
    }
  }
  public bool Equals(KeyPair other)
  {
    return other != null && other.Min == Min && other.Max == Max;
  }
  public override bool Equals(object other)
  {
    return Equals(other as KeyPair);
  }
  public override int GetHashCode()
  {
    return unchecked(Max * 31 + Min);
  }
}

现在,这里的GetHashCode()不会是唯一的,但KeyPair本身将是独一无二的。理想情况下,哈希码彼此非常不同,以便更好地分布这些对象,但比上述要好得多取决于在实践中看到的实际值的信息。

字典将使用它来查找项目,但它也将使用Equals在哈希代码相同的项目之间进行选择。

(您可以通过拥有一个GetHashCode()总是只返回 0 的版本来试验这一点。它的性能会很差,因为碰撞会损害性能,并且这总是会碰撞,但它仍然有效(。

首先,42.GetHashCode()返回 42。其次,1 ^ 22 ^ 1相同,因此对数字进行排序实际上没有意义。第三,你的"哈希"函数非常弱,会产生很多冲突,这就是你观察缺陷的原因。

我现在能想到的有两种选择:

  • 使用稍微"强"的哈希函数
  • Dictionary<int, int>键替换为Dictionary<string, int>键,键是两个排序的数字,由您指定的任何字符分隔 - 例如 56-6472

鉴于 XOR 是可交换的(所以(a ^ b)总是与(b ^ a)相同(,在我看来,您的排序是错误的......我只是

(new {firstOrderId, secondOrderId}).GetHashCode()

.Net 将为匿名类型修复一个很好的分布式哈希实现。