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ść';
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ść';
To się nazywa tablica asocjacyjna
(ew. mapa
).
Spróbuj się pobawić z default property
, o ile się nie mylę w nazwie.
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;
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).
Dzięki wielkie.
@Patryk27:
Spróbuj się pobawić zdefault 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.
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;