代码之家  ›  专栏  ›  技术社区  ›  Chau Chee Yang

如何在敏感的TeQualityComparer中为TDictionary创建案例?

  •  9
  • Chau Chee Yang  · 技术社区  · 15 年前

    我有一个案例使用的是TDictionary:

    var D: TDictionary<string, integer>;
    begin
      D := TDictionary<string, integer>.Create(TCustomEqualityComparer.Create());
      try
        D.Add('One', 1);
        D.Add('Two', 2);
        D.Add('Three', 3);
    
        showmessage(inttostr(D.Items['One']));
        showmessage(inttostr(D.Items['TWO']));
      finally
        D.Free;
      end;
    end;
    

    类tcustomeQualityComparer是从复制的 Generics Defaults TEqualityComparer (Delphi) 对GetHashCode方法进行了细微修改:

    TCustomEqualityComparer = class(TEqualityComparer<string>)
    public
      function Equals(const Left, Right: string): Boolean; override;
      function GetHashCode(const Value: string): Integer; override;
    end;
    
    function TCustomEqualityComparer.Equals(const Left, Right: string): Boolean;
    begin
      Result := SameText(Left, Right);
    end;
    
    function TCustomEqualityComparer.GetHashCode(const Value: string): Integer;
    begin
      Result := BobJenkinsHash(Value[1], Length(Value) * SizeOf(Value[1]), 0);
    end;
    

    我希望tcustomeQualityComparer能够对键值执行不区分大小写的匹配。例如:

    D.Items['TWO']
    

    但是,我得到一个“找不到项目”的异常。我使用的是Delphi2010版本14.0.3513.24210。

    有人知道我的代码怎么了吗?

    3 回复  |  直到 6 年前
        1
  •  14
  •   tz.    12 年前
    uses System.Generics.Collections, System.Generics.Defaults;
    
    var
      D: TDictionary<string, Integer>;
    begin
      D := TDictionary<string, Integer>.Create(TIStringComparer.Ordinal); // ‹- this is the trick
      try
        D.Add('One', 1);
        .
        .
      finally
        D.Free;
      end;
    end;
    
        2
  •  3
  •   Uwe Raabe    12 年前

    对于返回等于true的所有值,哈希代码必须相同!在将gethashcode发送到哈希函数之前,请尝试将其值设为大写。

        3
  •  2
  •   HeartWare    6 年前

    谢谢。我已经更改了tcustomeQualityComparer.getHashCode,它的工作方式如您所说:

    function TCustomEqualityComparer.Equals(const Left, Right: string): Boolean;
    begin
      {$IFDEF UNICODE }
        Result := (Left.ToUpper = Right.ToUpper);
      {$ELSE }
        Result := SameText(Left, Right);
      {$ENDIF }
    end;
    
    function TCustomEqualityComparer.GetHashCode(const Value: string): Integer;
    var s: string;
    begin
      s := {$IFDEF UNICODE } Value.ToUpper {$ELSE } UpperCase(Value) {$ENDIF };
      Result := BobJenkinsHash(s[1], Length(s) * SizeOf(s[1]), 0);
    end;