Arrays
Pascal (Delphi) language doesn't have associative arrays in the language. There are just arrays with an index of an ordinal type (i.e. integer, not string or a floating-point number). There are multi-dimensional arrays and, recently, dynamic arrays, but the index is ordinal anyway.
However, standard library units (Classes.pas and System.Generics.Collections.pas) provide classes that implement the functionality you are speaking about.
You can use new Delphi Generics, particularly TDictionary, for truly associative arrays, or the good old TStringList, just for plain string lists. The TStringList class have been extended with the Name+Delimiter+Value functionality in newer versions of Delphi. For the pairs, the TStringList is slower than TDictionary of Delphi Generics, because it just stores plain strings inside and parses them on-the-fly. The Generics, however, use efficient structures that add and remove items quickly, use hashes of the values, and thus are very fast. In the TStringList, to the contrary, random insertions and deletions are slow - O(N), but getting a string by index is momentary - O(1).
Generics
uses
System.Generics.Collections,
procedure TestGenerics;
type
TKey = string;
TValue = string;
TKeyValuePair = TPair<TKey, TValue>;
TStringDictionary = TDictionary<TKey, TValue>;
var
D: TStringDictionary;
K: TKey;
V: TValue;
P: TKeyValuePair;
ContainsKey, ContainsValue: Boolean;
begin
D := TStringDictionary.Create;
D.Add('Bulgaria', 'Bulgarian');
D.Add('Croatia', 'Croatian Italian');
K := D.Items['Bulgaria'];
P := D.ExtractPair('Bulgaria');
ContainsKey := D.ContainsKey('Bultaria');
ContainsValue := D.ContainsValue('Bultarian');
// you do not need to free P, since it is just a record in the stack
D.Free;
end;
String List
Please note that the authors of Delphi call it Name+Value pairs, not Key+Value pairs, because, in the TStringList, these are not actually "Keys" in the means of fast access, it is just parts of the same string. They don't have special sorted indexing capabilities - just regular sorted TStringList if you wish.
Also be aware that when the TStringList object includes strings that are name-value pairs or just names, read Keys to access the name part of a string. If the string is not a name-value pair, Keys returns full string. Assigning Keys will write new name for name-value pair. This is in contrast to Names property.
Also, take into consideration, that TStringList uses continuous memory space to hold pointers to the string data, so when you add new strings, it uses a pre-allocated space for a few more entries, but then allocates a new larger memory block and copies old pointers to the new one, releasing an old block. So, if you know in advance the number of items, it's better to tell that number to TStringList to it would pre-allocate the buffer once and for all. That would not prevent from enlarging the buffer later, should you need more items then.
uses
Classes;
procedure TestStringList;
var
SL: TStringList;
FullString, Separator, FName, FValue: string;
begin
SL := TStringList.Create;
SL.AddPair('Bulgaria', 'Bulgarian'); // add a Name -> Value pair
SL.AddPair('Croatia', 'Croatian Italian');
// Names and KeyNames is the same
FName := SL.Names[0]; // Indicates the name part of strings that are name-value pairs.
FName := SL.KeyNames[0];
FValue := SL.Values['Bulgaria']; // Represents the value part of a string associated with a given name, on strings that are name-value pairs.
FValue := SL.ValueFromIndex[0]; // Represents the value part of a string with a given index, on strings that are name-value pairs.
FullString := SL.Strings[0]; // References the strings in the list by their positions (the whole Name+Separator+Value pair)
Separator := SL.NameValueSeparator; // Indicates the character used to separate names from values.
SL.Free;
end;