Lesson 12 · 12 of 20
Generics.Collections · Pascal
Count sales per city with TDictionary and sort the result with TList, the generic collections in Free Pascal's Generics.Collections unit.

The `Generics.Collections` unit offers the same collections as Delphi: TList<T>, TDictionary<K, V>, TObjectList<T>, TQueue<T> and more. Here TSales is a dictionary from city to number of orders and TCityList a list of strings.
The loop counts the orders in Orders. `TryGetValue` looks up the city and, if it is there, puts its count in count and returns True; then sales[city] := count + 1 updates it. If not, Add creates it with 1. Careful: Add with an existing key raises an exception; for "add or replace" there is AddOrSetValue.
A dictionary stores its keys by *hash*, so its order cannot be trusted and could change with another version or other data. For stable output, the program copies the keys into the list with cities.AddRange(sales.Keys), sorts them with cities.Sort and walks the list, asking sales[city] for each count.
Count says how many cities there are and `ContainsKey` asks about a key safely. Both collections are freed in the finally block. When compiling, Free Pascal 3.2.2 shows a few warnings that come from the unit itself (Constructing a class ... with abstract method): they are internal to the library and do not affect your program.
Code · main.pas
program main;uses Generics.Collections;type TCityList = specialize TList<String>; TSales = specialize TDictionary<String, Integer>;const Orders: array[0..6] of String = ('Madrid', 'Sevilla', 'Madrid', 'Bilbao', 'Sevilla', 'Madrid', 'Valencia');var sales: TSales; cities: TCityList; city: String; count: Integer;begin sales := TSales.Create; cities := TCityList.Create; try for city in Orders do if sales.TryGetValue(city, count) then sales[city] := count + 1 else sales.Add(city, 1); // A dictionary has no fixed order: copy the keys and sort them cities.AddRange(sales.Keys); cities.Sort; for city in cities do WriteLn(city:9, sales[city]:3); WriteLn('Cities: ', sales.Count, ', any in Malaga: ', sales.ContainsKey('Malaga')); finally cities.Free; sales.Free; end;end.Output · fpc main.pas && ./main
Bilbao 1 Madrid 3 Sevilla 2 Valencia 1 Cities: 4, any in Malaga: FALSE
Key points
TDictionary<K, V>finds values by key very quickly.TryGetValuereads without raising if the key is missing.Addfails on duplicate keys;AddOrSetValuedoes not.- Dictionary order is not guaranteed: sort the keys separately.
TList<T>hasAddRange,Sortandfor ... in.
Exercise
Create a second TDictionary<String, Double> with the amount of each order and print, city by city in alphabetical order, how much has been invoiced.