2015-01-07 13 views
14

Bạn có thể sử dụng bản ghi làm Giá trị khóa trong TDictionary không? Tôi muốn tìm các đối tượng dựa trên sự kết hợp của chuỗi, số nguyên và số nguyên.delphi Sử dụng các bản ghi làm khóa trong TDictionary

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; 

lợi nhuận này đối tượng 2.

Trả lời

18

Vâng, bạn có thể sử dụng hồ sơ như là chìa khóa trong một TDictionary nhưng bạn nên cung cấp trình duyệt IEqualityComparer của riêng bạn khi tạo từ điển vì từ điển mặc định cho bản ghi chỉ thực hiện so sánh nhị phân câm của ghi lại. Điều này không thành công cho một bản ghi có chứa một chuỗi vì nó chỉ so sánh con trỏ của chuỗi đó có thể khác nhau ngay cả khi chuỗi chứa cùng một giá trị.

Như một Comparer sẽ trông như thế này:

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; 
+0

thnx cho mã. Bobjenkinshash là gì? và tại sao nó lại cần thiết? Băm của tôi trông như thế này tmpStr: = ''; cho I: = 1 đến Value.App.length do tmpStr: = tmpStr + inttostr (ord (Value.app [i])); tmpStr: = tmpStr + inttostr (Value.ID) + inttostr (Giá trị.Nr); kết quả: = StrToIntDef (tmpStr, -1); –

+1

Đó là từ Generics.Defaults và được sử dụng cho tất cả các chức năng GetHashCode trong các bộ so sánh. Mã của bạn sẽ dễ dàng bị lỗi vì nhiều lý do - xin đừng làm như vậy. –

+0

Điều này sẽ dẫn đến lỗi kiểm tra phạm vi cho các chuỗi trống có bật kiểm tra phạm vi. Nó sẽ được tốt đẹp để làm thois mà không cần phải gọi BobJenkinsHash mà cảm thấy mức độ khá thấp. Nó sẽ ngắn gọn hơn khi sử dụng các phương thức anon và Xây dựng hơn là khai báo một lớp. Đôi khi cảm thấy tốt hơn. +1 –

Các vấn đề liên quan