Dynamiczna tablica z indeksem tekstowym

0

Witam,
Czy jest możliwe w Delphi zadeklarowanie dynamicznej tablicy z indeksem tekstowym? Chodzi mi taki typ tablicy jak jest w PHP:

tablica['indeks'] = 'wartość';
1

To się nazywa tablica asocjacyjna (ew. mapa).
Spróbuj się pobawić z default property, o ile się nie mylę w nazwie.

2
unit Generics.Collections 

var
  Dict: TDictionary<string,string>;
  myValue: string;
....
Dict := TDictionary<string,string>.Create;
try
  Dict.Add('hostname', 'localhost');
  Dict.Add('database', 'test');
  //etc.
  myValue := Dict['hostname'];
finally
  Dict.Free;
end;
0

Tak jak napisał poprzednik - używa się do tego słowników (w c++ to się nazywa mapa w C# i Delphi słownik, w innych jeszcze językach (np. php) - tablica asocjacyjna).

0

Dzięki wielkie.

2

@Patryk27:
Spróbuj się pobawić z default property, o ile się nie mylę w nazwie.

Jeśli posiada się właściwość indeksowaną to faktycznie wystarczy zakończyć ją modyfikatorem default. Dzięki temu, aby odwołać się do elementu spod konkretnego indeksu takiej właściwości, nie trzeba będzie pisać jej nazwy.

Przykład:

type
  TMyContainer = {..}
  {..}
  private
    function GetItem(const AName: String): String;
    procedure SetItem(const AName, AValue: String);
  public
    property Item[const AName: String]: String read GetItem write SetItem; default;
  end;

Przykład użycia:

var
  Container: TMyContainer;
  Value: String;
  
{..}

// pobranie ciągu
Value := Container['item name'];

// modyfikacja ciągu
Container['item name'] := 'item value';

I w tym momencie mamy przystosowanie własnego typu kontenera do wymaganej przez pytacza składni. Natomiast odpowiadając dokładnie na zadane pytanie - dla zwykłej macierzy raczej nie ma takiej możliwości.

Nie wiem jak sprawa wygląda we współczesnym Delphi, jednak z ciekawości spróbowałem pod Lazarusem stworzyć helper dla zwykłego typu tablicowego. Niestety, ale zwykłe macierze indeksowane są liczbami i próba ominięcia tego spowoduje niezgodność typów. Wyglądało by to dla przykładu tak:

{$MODESWITCH TYPEHELPERS}
  
type
  TMyContainer = array of String;
  
type
  TMyContainerHelper = type helper for TMyContainer
  private
    function GetItem(const AName: String): String;
    procedure SetItem(const AName, AValue: String);
  public
    property Items[const AName: String]: String read GetItem write SetItem; default;
  end;

Kod kompiluje się poprawnie, jednak próba odwołania się do elementu macierzy za pomocą nazwy powoduje wystąpienie błędu kompilacji. Właśnie ze względu na niezgodność typu danych indeksu podanego z typem indeksu oczekiwanego.

Podsumowując - nie sprawdzę czy istnieje jakiś fajny hack w Delphi, bo nie posiadam żadnego. Natomiast w Lazarusie da się to zrobić dla różnych typów nieindeksowanych domyślnie, korzystając z natywnej możliwości posiadania przez daną strukturę właściwości (zaawansowane rekordy, stare obiekty i klasy) lub z helperów.

1

Był kiedyś taki art tutaj Tablice asocjacyjne w Delphi dokładając do tego jeszcze generyki można by pokusić się o coś ciekawego.
Wyskrobałem na razie coś takiego:

  TMagicArray = record
    DynArray: array of Variant;
    function GetItem(const Name: Variant): Variant;
    procedure SetItem(const Name: Variant; Value: Variant);
    procedure Clear;
    procedure AddItem(Name: string; Value: Pointer);
    procedure RemItem(Name: string);
    property Items[const Name: Variant]: Variant read GetItem write SetItem; default;
  end;

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.