Tuesday, April 20, 2010

TurboHashedStringList at version 1.2

Thanks to SportsGuy, TurboHashedStringList is updated to version 1.2.
There are two new properties added to the class:
- Objects
- ObjectsByName

here are their definition:
property Objects[Index: Integer]: TObject
      read GetObject write PutObject;
    property ObjectsByName[Name: String; bCaseSensitive: Boolean]: TObject
      read GetObjectByName write PutObjectByName;
and implementation if you wish to update manually:
function TurboHashedStringList.GetObject(Index: Integer): TObject;
begin
  if (Index < 0) or (Index >= Self.Count) then
    Result := NIL;
  Result := PStringRec(FList[Index])^.ObjectRef;
end; // function TurboHashedStringList.GetObject(Index: Integer): TObject;

procedure TurboHashedStringList.PutObject(Index: Integer;
  AObject: TObject);
begin
  if (Index < 0) or (Index >= Self.Count) then
    Exit;
  PStringRec(FList[Index])^.ObjectRef := AObject;
end; // procedure TurboHashedStringList.PutObject(Index: Integer;

function TurboHashedStringList.GetObjectByName(Name: String;
  bCaseSensitive: Boolean): TObject;
var
  Index: Integer;
begin
  Index := IndexOfName(Name, bCaseSensitive);
  if Index >= 0 then
    Result := Objects[Index]
  else
    Result := NIL;
end; // function TurboHashedStringList.GetObjectByName(Name: String;

procedure TurboHashedStringList.PutObjectByName(Name: String;
  bCaseSensitive: Boolean; const Value: TObject);
var
  Index: Integer;
begin
  Index := IndexOfName(Name, bCaseSensitive);
  if Index >= 0 then
    PStringRec(FList[Index])^.ObjectRef := Value;
end; // procedure TurboHashedStringList.PutObjectByName(Name: String;
Alternatively you can download the class as a tiny zip file by clicking on this sentance.

11 comments:

  1. Dorin, I don't think the Values property is working right. I'm pressed for time right now, but sometime over the weekend I'll work up a simple test prog to make sure. The app I'm calling the Values property in right now isnt' getting the job done, despite the list's Text property giving me exactly what I expect.

    ReplyDelete
  2. I'll look into it somewhere around Sunday/Monday, I'm a bit pressed for the time also...
    By the way, I've started working on a generic class that will by similar to this but in stead of TObject it will be a generic type -- more flexibility + Unicode.
    I need to do a bit more testing, the hash functions are not working as expected in Unicode version of Delphi therefore I was forced to change them.

    ReplyDelete
  3. In D2010 you can use Generic custom List <>.

    MyIntList := TMylist.Create;

    ReplyDelete
  4. MyIntList := TMylist.Create;

    ReplyDelete
  5. // MyIntList := TMylist . Create ;

    ReplyDelete
  6. // MyIntList := TMylist << Integer >>.Create;

    this blog remove <><><<< >>>>

    ReplyDelete
  7. yes, but this version was created for Delphi 7 which does not have generics...

    ReplyDelete
  8. I TEST and the first search have very good time but when i do a lot of more search in the same TurboHashedStringList the time incremental or if i call the same TurboHashedStringList in other procedure the time is the same a commom stringlist and dont create again the TurboHashedStringList if the same in all search y use indexofname but dont understand .
    thank in advance

    ReplyDelete
  9. @Hernan if you take a closer look at the code you will see that IndexOfName returns the index of a item in the list, basically when you call the method Add('a string value') the name is 'a string value'.

    ReplyDelete
  10. Thanks for sharing this code, in test I've conducted it is very fast!

    But I found a small bug:
    Because the hashes are not unique, I've come across a situation where 2 different strings had identical hashes.
    I've made this change to the GetValue function to compensate:


    function TurboHashedStringList.GetValue(Name: String; bCaseSensitive: Boolean): String;
    var
    Index: Integer;
    begin
    Result := EmptyStr;
    if StringExists(Name, Index, bCaseSensitive) then
    if Name = PStringRec(FList[Index])^.Name^.Value then
    Result := PStringRec(FList[Index])^.Value^.Value;
    end;


    I've added the second if in order to be sure that the Name is the same we want.

    ReplyDelete
    Replies
    1. Hi noctrex, it seems that the hash function is flawed, can you give me an example of two different strings having the same hash value and delphi version please?

      Your fix is ok-ish, but it will reduce the speed of the GetValue function, the overhead is small on few items, but when we're talking hundreds or thousands of items, then you can see the difference.

      I suggest you look for a better suited string hash function, it seems that the one I've used is not the best...

      Delete

Blogroll(General programming and Delphi feeds)