delphi hashmap?
Asked Answered
O

3

16

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!

Orb answered 4/4, 2011 at 8:14 Comment(1)
Use Generics.Collections.TDictionary<TKey,TValue>Brickwork
D
20

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

Downtime answered 4/4, 2011 at 8:20 Comment(4)
oh, thanks. this looks nice. are there iterators for this? in java i use a recursive method that gives me every combo of key-value-pairs (note:values are a stringlist in delphi-context...)Orb
You can use for in to enumerate the key value pairsBrickwork
my code looks similar like this (found it here on stackoverflow): https://mcmap.net/q/748889/-recursively-or-iteratively-retrieve-key-value-combinations-from-a-hashmap. how does this translate to delphi?Orb
@someuser: see my addition, maybe this helps to get startedDowntime
A
5

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;
Argybargy answered 4/4, 2011 at 9:23 Comment(1)
I just used this wrapper for my .map file reader, and it works like a charm. Very fast and easy to use. The .map file is read in no time, and symbol names are added into an internal list using fast hashing. See this linkArgybargy
D
5

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.

Demurrage answered 30/12, 2014 at 17:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.