Pergunta

Existe uma variante insensível ao caso da função de hash de Bob Jenkins?

Generics.Defaults.BobJenkinsHash

fornece uma função de hash rápida. Infelizmente, ele não pode ser usado em combinação com uma função de comparação insensível ao caso como So

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;

Isso ocorre porque o tdictionary compara primeiro os códigos de hash e depois usa a comparação fornecida ao verificar a igualdade.

Claro que eu poderia usar maiúsculas no meu GetHashCode Função, mas me perguntei se seria mais rápido se eu pudesse de alguma forma modificar a função de hash.

Foi útil?

Solução

Não, não há uma versão invariante de casos da função de hash. Case inferior ou superior todas as cordas antes de passá -las para a função de hash.

Outras dicas

Seria um pouco mais rápido, mas prejudica muito sua manutenção. Raramente existe uma boa razão para esse tipo de micro-otimização. Basta converter suas cordas em caixa inferior ou superior antes de hash como você sugeriu.

"Devemos esquecer pequenas eficiências, digamos cerca de 97% das vezes: a otimização prematura é a raiz de todo o mal. No entanto, não devemos deixar passar nossas oportunidades nesse 3% crítico. Um bom programador não será preso à complacência por tal Raciocínio, ele será aconselhável olhar cuidadosamente para o código crítico; mas somente depois que esse código foi identificado " - Donald Knuth

IMO, toda a questão está errada. Para citar o Artigo da Wikipedia sobre funções de hash:

UMA função hash é qualquer procedimento bem definido ou função matemática que converte uma quantidade grande e possivelmente de tamanho variável de dados em um pequeno dado, geralmente um número inteiro único que pode servir como um índice para uma matriz.

Observe a "quantidade de dados" - não há tipo especificado e, de fato, a função de hash bob jenkins tem um parâmetro não topado const Data apontando para os dados a serem hash. Como os dados de entrada não são necessariamente uma sequência de caracteres, não há como calcular um valor de hash "insensível ao caso". E mesmo se fosse uma sequência de caracteres - a parte superior ou inferior dependeria do conjunto de caracteres e da codificação. Então, você precisaria ter funções de hash diferentes para seqüências de caracteres ASCII, Strings codificadas UTF-8, Strings codificadas UTF-16 LE, ... (você entendeu a ideia).

Eu também precisava dessa função em um projeto. One-a-Time Hash de Bob Jenkin:

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;        

Se o Asciiony for definido, ele também deve dar o mesmo hash para as cordas UTF-8 e Latin1.

Não se esqueça de desativar a verificação de transbordamento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top