delphi hashmap?

16,909

Solution 1

In Delphi 2009 and higher, you can use TDictionary<string, TStringlist> using Generics.Collections.

In older versions, you can use TStringlist where every item in the TStringlist has an associated object value of type TStrings.

The Docwiki has a page to get started with TDictionary

Solution 2

Since Delphi 6, the set of predefined container classes includes TBucketList and TObjectBucketList. These two lists are associative, which means they have a key and an actual entry. The key is used to identify the items and search for them. To add an item, you call the Add method with two parameters: the key and the data. When you use the Find method, you pass the key and retrieve the data. The same effect is achieved by using the Data array property, passing the key as parameter.

Solution 3

If you have an older version of Delphi (Delphi 6 and up), you could also use a dynamic array of record, then our TDynArray or TDynArrayHashed wrappers to create a dictionary with one field of the dynamic array records. See this unit.

The TDynArrayHashed wrapper was developed to be fast.

Here is some sample code (from supplied unitary tests):

var ACities: TDynArrayHashed;
    Cities: TCityDynArray;
    CitiesCount: integer;
    City: TCity;
    added: boolean;
    N: string;
    i,j: integer;
const CITIES_MAX=200000;
begin
  // valide generic-like features
  // see http://docwiki.embarcadero.com/CodeExamples/en/Generics_Collections_TDictionary_(Delphi)
  ACities.Init(TypeInfo(TCityDynArray),Cities,nil,nil,nil,@CitiesCount);
  (...)
  Check(ACities.FindHashed(City)>=0);
  for i := 1 to 2000 do begin
    City.Name := IntToStr(i);
    City.Latitude := i*3.14;
    City.Longitude := i*6.13;
    Check(ACities.FindHashedAndUpdate(City,true)=i+2,'multiple ReHash');
    Check(ACities.FindHashed(City)=i+2);
  end;
  ACities.Capacity := CITIES_MAX+3; // make it as fast as possible
  for i := 2001 to CITIES_MAX do begin
    City.Name := IntToStr(i);
    City.Latitude := i*3.14;
    City.Longitude := i*6.13;
    Check(ACities.FindHashedAndUpdate(City,true)=i+2,'use Capacity: no ReHash');
    Check(ACities.FindHashed(City.Name)=i+2);
  end;
  for i := 1 to CITIES_MAX do begin
    N := IntToStr(i);
    j := ACities.FindHashed(N);
    Check(j=i+2,'hashing with string not City.Name');
    Check(Cities[j].Name=N);
    CheckSame(Cities[j].Latitude,i*3.14);
    CheckSame(Cities[j].Longitude,i*6.13);
  end;
end;

So for your problem:

type
  TMyMap = record
    Key: string;
    Value: array of string;
  end;
  TMyMapDynArray = array of TMyMap;

var
  Map: TMyMap;
  Maps: TMyMapDynArray;
  MapW: TDynArrayHashed;
  key: string;
  i: integer;
begin
  MapW.Init(TypeInfo(TMyMapDynArray),Maps);
  Map.Key := 'Some key';
  SetLength(Map.Value,2);
  Map.Value[0] := 'One';
  Map.Value[1] := 'Two';
  MapW.FindHashedAndUpdate(Map,true); // ,true for adding the Map content
  key := 'Some key';
  i := MapW.FindHashed(key);
  // now i=0 and Maps[i].Key=key
  for i := 0 to MapW.Count-1 do // or  for i := 0 to high(Maps) do
    with Maps[i] do
    // now you're enumerating all key/value pairs
end;
Share:
16,909
someuser
Author by

someuser

Updated on June 02, 2022

Comments

  • someuser
    someuser about 2 years

    i have java-code filling a hashmap from a textfile.
    HashMap<String, String[]> data = new HashMap<String, String[]>();

    i use this to make key-value-pairs. the values are an array of string. i have to iterate over every possible combo of the key-value-pairs (so also have to iterate over the String[]-array). This works with java but now i have to port this to delphi. is it possible to do so? and how? thanks!