On 13.04.2011 17:39, Luc wrote: > For a new project i need to implement a special structure In Delphi > which exists in Python. > > Is there an equivalent structure in DIContainers for the python > Dict(set) implementation. > This is a structure which hashes to a uniqe key but the value consists > of multiple sets. > > example in python: > > db=defaultdict(set) > db[1,2].add('test1') > db[1,2].add('test 2') > db[1,2].add('test 3') > print db > > gives as result: > > defaultdict(<type 'set'>, {(1, 2): set(['test1', 'test 2', 'test 3'])}) > > hask key (1,2) has multiple results as a set (test1,test2,test3) I do not know Python, but a TDIHash container can be set up with one type for the key and another type for the data. Both can be different types, for example objects or records, and can contain multiple fields. The TDIKeyHandler and TDIItemHandler instances which are passed to the TDIHash constructor determine how the container handles its keys and items, respectively: constructor TDIHash.Create( const AItemHandler: TDIItemHandler; const AKeyHandler: TDIKeyHandler); Below is a very simple console example to show how this may be implemented in practice. Please modify according to your actual needs. Ralf //-------------------------------------------------------------------- { Minimal demo for a TDIHash container with multiple key and item types. } program Hash_Types; {$APPTYPE Console} {$I DI.inc} uses {$IFDEF FastMM}FastMM4, {$ENDIF}SysUtils, DIContainers; //-------------------------------------------------------------------- { Define they key type and the TDIKeyHandler callback functions. } type TKey = class public s1: string; s2: string; end; { Store the TKey object to the reserved memory. This moves the TKey to the TDIHash container. It will be freed by FreeKey_TKey below. } procedure StoreKey_TKey(const PKeySource, PKeyDest: Pointer); begin TKey(PKeyDest^) := TKey(PKeySource^); end; procedure FreeKey_TKey(const PKey: Pointer); begin TKey(PKey^).Free; end; { Calculate a simple hash value made up of two key fields. } function HashKey_TKey(const PKey: Pointer): Cardinal; begin with TKey(PKey^) do Result := HashKey_BufferCI(PChar(s1), Length(s1)) xor HashKey_BufferCI(PChar(s2), Length(s2)); end; { Compare two keys. Needed to resolve hash collisions. } function SameKeys_TKey(const PKey1, PKey2: Pointer): Boolean; begin Result := (TKey(PKey1^).s1 = TKey(PKey2^).s1) and (TKey(PKey1^).s2 = TKey(PKey2^).s2); end; var KeyHandler: TDIKeyhandler = nil; function GetKeyHandler: TDIKeyhandler; begin if not Assigned(KeyHandler) then begin KeyHandler := TDIKeyhandler.Create; KeyHandler.KeySize := SizeOf(TKey); KeyHandler.OnStoreKey := StoreKey_TKey; KeyHandler.OnFreeKey := FreeKey_TKey; KeyHandler.OnHashKey := HashKey_TKey; KeyHandler.OnSameKeys := SameKeys_TKey; end; Result := KeyHandler; end; //-------------------------------------------------------------------- { Define they key type and the TDIItemHandler callback functions. } type TItem = class(TObject) public i1: string; i2: Integer; i3: Double; end; TItem_ptr = ^TItem; procedure InitItem_TItem(const PItem: Pointer); begin TItem(PItem^) := nil; end; procedure FreeItem_TItem(const PItem: Pointer); begin TItem(PItem^).Free; end; var ItemHandler: TDIItemHandler = nil; function GetItemHandler: TDIItemHandler; begin if not Assigned(ItemHandler) then begin ItemHandler := TDIItemHandler.Create; ItemHandler.ItemSize := SizeOf(TItem); ItemHandler.OnInitItem := InitItem_TItem; ItemHandler.OnFreeItem := FreeItem_TItem; end; Result := ItemHandler; end; //-------------------------------------------------------------------- { Small test of the above. } const Count = 1000; var i: Integer; Key: TKey; ItemPtr: TItem_ptr; Hash: TDIHash; begin // Create Hash Hash := TDIHash.Create(GetItemHandler, GetKeyHandler); // Add Items for i := 0 to Count do begin { Create the key. This must be passed to Hash.InsertItemByKey() which takes an untyped parameter. } Key := TKey.Create; Key.s1 := IntToStr(i); Key.s2 := IntToStr(i); { Insert the key. This returns a pointer to the item. } ItemPtr := Hash.InsertItemByKey(Key); { Use the Item pointer to create the item and store data. } ItemPtr^ := TItem.Create; ItemPtr^.i1 := IntToStr(i); ItemPtr^.i2 := i; ItemPtr^.i3 := i; end; // Check Items Key := TKey.Create; // Temp key used for lookup. for i := 0 to Count do begin Key.s1 := IntToStr(i); Key.s2 := IntToStr(i); ItemPtr := Hash.PItemOfKey(Key); if not Assigned(ItemPtr) or (ItemPtr^.i2 <> i) then WriteLn('Error at ', i); end; Key.Free; // Free Hash. This frees the key and item instances. Hash.Free; KeyHandler.Free; ItemHandler.Free; WriteLn; WriteLn('Done - Press ENTER to Exit'); ReadLn; end. _______________________________________________ Delphi Inspiration mailing list yunqa@xxxxxxxxxxxxx //www.freelists.org/list/yunqa