unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Generics.Collections;

// user-defined type of the values in the dictionary
type
  TCity = record
    Country: ShortString;
    Latitude, Longitude: Single;
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure KNotify(Sender: TObject; const Item: String; Action: TCollectionNotification);
    procedure VNotify(Sender: TObject; const Item: TCity; Action: TCollectionNotification);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// BeginExample: Generics.Collections.TDictionary
// Property: Generics.Collections.TDictionary.Count
// Property: Generics.Collections.TDictionary.Items
// Property: Generics.Collections.TDictionary.Keys
// Property: Generics.Collections.TDictionary.Values
// Method: Generics.Collections.TDictionary.Add
// Method: Generics.Collections.TDictionary.AddOrSetValue
// Method: Generics.Collections.TDictionary.Clear
// Method: Generics.Collections.TDictionary.ContainsKey
// Method: Generics.Collections.TDictionary.ContainsValue
// Method: Generics.Collections.TDictionary.TKeyCollection.GetEnumerator
// Method: Generics.Collections.TDictionary.TValueCollection.GetEnumerator
// Method: Generics.Collections.TDictionary.Remove
// Method: Generics.Collections.TDictionary.TrimExcess
// Event: Generics.Collections.TDictionary.OnKeyNotify
// Event: Generics.Collections.TDictionary.OnValueNotify

// BeginCode
{
This example demonstrates the usage of the main methods and properties in TDictionary.
It uses the ShowMessage procedure and requires no visual components on the form.
}
procedure TForm1.KNotify(Sender: TObject; const Item: String;
  Action: TCollectionNotification);
begin
  { Show a message each time a key is added or removed }
  ShowMessage('The key "' + Item + '" was added/removed.');
end;

procedure TForm1.VNotify(Sender: TObject; const Item: TCity;
  Action: TCollectionNotification);
begin
  { Show a message each time a value is added or removed }
  ShowMessage('The value "' + Item.Country + '" was added/removed.');
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Dictionary: TDictionary<String, TCity>;
  City, Value: TCity;
  Key: String;
  temp: String;
  pair: TEnumerator<TPair<String, TCity>>;

begin
  { Create the dictionary }
  Dictionary := TDictionary<String, TCity>.Create;
  Dictionary.OnKeyNotify := KNotify;
  Dictionary.OnValueNotify := VNotify;

  { Add some key-value pairs to the dictionary }
  City.Country := 'Romania';
  City.Latitude := 47.16;
  City.Longitude := 27.58;
  Dictionary.Add('Iasi', City);

  City.Country := 'United Kingdom';
  City.Latitude := 51.5;
  City.Longitude := -0.17;
  Dictionary.Add('London', City);

  City.Country := 'Argentina';
  { Notice the wrong coordinates }
  City.Latitude := 0;
  City.Longitude := 0;
  Dictionary.Add('Buenos Aires', City);

  { Display the current number of key-value entries }
  ShowMessage('Number of pairs in the dictionary: ' +
  IntToStr(Dictionary.Count));

  // Try looking up "Iasi"
  if (Dictionary.TryGetValue('Iasi', City) = True) then
  begin
    ShowMessage(
    'Iasi is located in ' + City.Country +
    ' with latitude = ' + FloatToStrF(City.Latitude, ffFixed, 4, 2) +
    ' and longitude = ' + FloatToStrF(City.Longitude, ffFixed, 4, 2)
    );
  end
  else
    ShowMessage('Could not find Iasi in the dictionary');

  { Remove the "Iasi" key from dictionary }
  Dictionary.Remove('Iasi');

  { Make sure the dictionary's capacity is set to the no. of entries }
  Dictionary.TrimExcess;

  { Test if "Iasi" is a key in the dictionary }
  if Dictionary.ContainsKey('Iasi') then
    ShowMessage('The key "Iasi" is in the dictionary.')
  else
    ShowMessage('The key "Iasi" is not in the dictionary.');

  { Test if (Argentina, 0, 0) is a value in the dictionary }
  City.Country := 'United Kingdom';
  City.Latitude := 51.5;
  City.Longitude := -0.17;
  if Dictionary.ContainsValue(City) then
    ShowMessage('The value (United Kingdom, 51.5, -0.17) is in the dictionary.')
  else
    ShowMessage('The value (United Kingdom, 51.5, -0.17) is not in the dictionary.');

  { Update the coordinates to the correct ones }
  City.Country := 'Argentina';
  City.Latitude := -34.6;
  City.Longitude := -58.45;
  Dictionary.AddOrSetValue('Buenos Aires', City);

  { Generate the exception "Duplicates not allowed" }
  try
    Dictionary.Add('Buenos Aires', City);
  except
    on Exception do
      { ShowMessage('Could not add entry. Duplicates are not allowed.'); }
  end;

  { Display all countries }
  temp := 'All countries:' + #13;
  for Value in Dictionary.Values do
    temp := temp + #13 + Value.Country;
  ShowMessage(temp);

  { Iterate through all keys in the dictionary and display their coordinates }
  temp := 'All cities and their coordinates:' + #13;
  for Key in Dictionary.Keys do
    temp := temp + #13 + Key + ': ' + #13 +
    FloatToStrF(Dictionary.Items[Key].Latitude, ffFixed, 4, 2) + ', ' +
    FloatToStrF(Dictionary.Items[Key].Longitude, ffFixed, 4, 2) + #13;
  ShowMessage(temp);

  { Clear all entries in the dictionary }
  Dictionary.Clear;

  { There should be no entries at this point }
  ShowMessage('Number of key-value pairs in the dictionary: ' + IntToStr(Dictionary.Count));

  { Free the memory allocated for the dictionary }
  Dictionary.Destroy;
end;
// EndCode
// EndExample: Generics.Collections.TDictionary

end.

