是否有鲍勃詹金斯散列函数的情况下不敏感的变体?

Generics.Defaults.BobJenkinsHash

提供了一种快速散列函数。不幸的是它不能在组合使用等的情况下不敏感的比较功能,以便

TCustomStringComparer = class (TEqualityComparer <String>)
  function Equals(const Left, Right: String): Boolean; override;
  function GetHashCode(const Value: String): Integer; override;
end;
function TCustomStringComparer.Equals (const Left, Right : String) : Boolean;
begin
  Result := CompareText (Left, Right) = 0;
end;
function TCustomStringComparer.GetHashCode (const Value : String) : Integer;
begin
  Result := Generics.Defaults.BobJenkinsHash (Value [1], Length (Value) * SizeOf (Char), 0);
end;

这是因为TDictionary平等检查时首先比较哈希码,然后使用所提供的比较器。

当然,我可以在我的GetHashCode功能使用大写,但我不知道它是否会更快,如果我能以某种方式修改散列函数本身。

有帮助吗?

解决方案

没有,有哈希函数的任何情况下不变的版本。小写或大写它们传递给散列函数之前所有字符串。

其他提示

这将是稍快,但它伤害你的可维护性很多。很少有一个很好的理由,这种类型的微型优化。只要将您的字符串到大写或小写散列像你这样的建议了。

  

“我们应该忘记小   效率,说的大约97%   时间:过早的优化是   万恶之源。然而,我们不应该   通过我们的机会在   关键的3%。一个好的程序员会   不受这种被哄骗自满   推理,他将是明智的,看看   仔细关键代码;但   只有经过代码已经   确定了” - 高德纳

IMO的整个问题是错误的。引述上散列函数维基百科文章

  

一个的散列函数是大量的数据,可能是可变大小的量转换成一个小基准,通常是单个整数,可以用作索引,以任何明确定义的过程或数学函数的阵列。

请注意在“数据量” - 没有指定的类型,并且实际上鲍勃詹金斯散列函数具有一个无类型参数const Data指向待哈希数据。由于输入数据不一定是一个字符序列也没有办法来计算“不区分大小写”散列值。而且,即使它是一个字符序列 - 的大写或lowercasing将取决于字符集和编码。所以,你会需要有ASCII字符串,UTF-8编码字符串,UTF-16 LE编码字符串不同的散列函数,......(你的想法)。

我还需要这样的功能中的一个项目。鲍勃詹的一个在一次一个散列:

function hash(const s: string): cardinal;
var
  p, last: PByte;
begin
  if s = '' then exit(1);
  p := pbyte(pointer(s));
  last := p + length(s);
  result := 0;
  while p < last do begin
    if {$ifdef asciionly}p^ < 128{$else}true{$endif}  then begin
      result := result + p^;
      if (p^ >= ord('a')) and (p^ <= ord('z')) then result := result - ord('a') + ord('A');
      result := result + (result shl 10);
      result := result xor (result shr 6);
    end;
    inc(p);
  end;

  result := result + (result shl 3);
  result := result xor (result shr 11);
  result := result + (result shl 15);
end;        

如果asciionly被设置,它也应该给予对于UTF-8和latin1的字符串相同的哈希。

不要忘记停止溢出检查。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top