2009-10-23 76 views
9

我使用有一個殼體TDictionary:如何爲TDictionary創建一個不敏感的TEqualityComparer案例?

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'] 

但是,我收到「找不到項目」異常。我正在使用Delphi 2010版本14.0.3513.24210。

有誰知道我的代碼有什麼問題嗎?

回答

2

謝謝。我已經改變TCustomEqualityComparer.GetHashCode和它的作品如你所說:

function TCustomEqualityComparer.Equals(const Left, Right: string): Boolean; 
begin 
    Result := SameText(Left, Right); 
end; 

function TCustomEqualityComparer.GetHashCode(const Value: string): Integer; 
var s: string; 
begin 
    s := UpperCase(Value); 
    Result := BobJenkinsHash(s[1], Length(s) * SizeOf(s[1]), 0); 
end; 
3

對於返回Equals = true的所有值,HashCode必須相同!在將它發送到您的HashFunction之前,請嘗試在GetHashCode中將值設爲大寫。

+0

確定原來的Equals已經是不區分大小寫? 這是在單元Generics.Defaults.pas中定義的原始等於方法: 函數Equals_UString(Inst:PSimpleInstance; const Left,Right:UnicodeString):Boolean; 開始 結果:=左=右; 結束; – 2009-10-24 01:05:27

+0

你是對的!我混淆了最初的實現和一個例子。 – 2009-10-24 07:46:25

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;