delphi 在 TDictionary 中使用记录作为键
delphi Using records as key in TDictionary
你能在TDictionary中使用一条记录作为Key值吗?我想根据字符串、整数和整数的组合查找对象。
TUserParKey=record
App:string;
ID:integer;
Nr:integer;
end;
...
var
tmpKey:TUserParKey;
tmpObject:TObject;
begin
tmpObject:= TTObject.Create(1);
tmpKey.App:='1';
tmpKey.ID :=1;
tmpKey.Nr :=1;
DTUserPars.Add(tmpKey,tmpObject)
...
var
tmpKey:TUserParKey;
begin
tmpKey.App:='1';
tmpKey.ID :=1;
tmpKey.Nr :=1;
if not DTUserPars.TryGetValue(tmpKey,Result) then begin
result := TTObject.Create(2);
end;
这个 returns 对象 2.
是的,您可以将记录用作 TDictionary 中的键,但您应该在创建字典时提供自己的 IEqualityComparer,因为记录的默认字典只是对记录进行哑二进制比较。
对于包含字符串的记录,这会失败,因为它只是比较该字符串的指针,即使该字符串包含相同的值,该指针也可能不同。
这样的比较器看起来像这样:
type
TUserParKeyComparer = class(TEqualityComparer<TUserParKey>)
function Equals(const Left, Right: TUserParKey): Boolean; override;
function GetHashCode(const Value: TUserParKey): Integer; override;
end;
function TUserParKeyComparer.Equals(const Left, Right: TUserParKey): Boolean;
begin
Result := (Left.App = Right.App) and (Left.ID = Right.ID) and (Left.Nr = Right.Nr);
end;
function TUserParKeyComparer.GetHashCode(const Value: TUserParKey): Integer;
begin
Result := BobJenkinsHash(PChar(Value.App)^, Length(Value.App) * SizeOf(Char), 0);
Result := BobJenkinsHash(Value.ID, SizeOf(Integer), Result);
Result := BobJenkinsHash(Value.Nr, SizeOf(Integer), Result);
end;
我最好的方法应该是联合基本类型的默认哈希码。
例如:
Value.App.GetHashCode + Value.ID.GetHashCode + Value.Nr.GetHashCode;
您可以使用由序列化记录组成的字符串,而不是使用记录作为键。您可以使用 https://github.com/hgourvest/superobject 之类的东西来进行序列化。
由于字符串具有 built-in 比较语义和哈希码,因此您无需编写比较和哈希码函数。
你能在TDictionary中使用一条记录作为Key值吗?我想根据字符串、整数和整数的组合查找对象。
TUserParKey=record
App:string;
ID:integer;
Nr:integer;
end;
...
var
tmpKey:TUserParKey;
tmpObject:TObject;
begin
tmpObject:= TTObject.Create(1);
tmpKey.App:='1';
tmpKey.ID :=1;
tmpKey.Nr :=1;
DTUserPars.Add(tmpKey,tmpObject)
...
var
tmpKey:TUserParKey;
begin
tmpKey.App:='1';
tmpKey.ID :=1;
tmpKey.Nr :=1;
if not DTUserPars.TryGetValue(tmpKey,Result) then begin
result := TTObject.Create(2);
end;
这个 returns 对象 2.
是的,您可以将记录用作 TDictionary 中的键,但您应该在创建字典时提供自己的 IEqualityComparer,因为记录的默认字典只是对记录进行哑二进制比较。 对于包含字符串的记录,这会失败,因为它只是比较该字符串的指针,即使该字符串包含相同的值,该指针也可能不同。
这样的比较器看起来像这样:
type
TUserParKeyComparer = class(TEqualityComparer<TUserParKey>)
function Equals(const Left, Right: TUserParKey): Boolean; override;
function GetHashCode(const Value: TUserParKey): Integer; override;
end;
function TUserParKeyComparer.Equals(const Left, Right: TUserParKey): Boolean;
begin
Result := (Left.App = Right.App) and (Left.ID = Right.ID) and (Left.Nr = Right.Nr);
end;
function TUserParKeyComparer.GetHashCode(const Value: TUserParKey): Integer;
begin
Result := BobJenkinsHash(PChar(Value.App)^, Length(Value.App) * SizeOf(Char), 0);
Result := BobJenkinsHash(Value.ID, SizeOf(Integer), Result);
Result := BobJenkinsHash(Value.Nr, SizeOf(Integer), Result);
end;
我最好的方法应该是联合基本类型的默认哈希码。
例如:
Value.App.GetHashCode + Value.ID.GetHashCode + Value.Nr.GetHashCode;
您可以使用由序列化记录组成的字符串,而不是使用记录作为键。您可以使用 https://github.com/hgourvest/superobject 之类的东西来进行序列化。
由于字符串具有 built-in 比较语义和哈希码,因此您无需编写比较和哈希码函数。