fpc/packages/rtl-generics/examples/thashmap/thashmapproject.lpr
michael d4f2a593d4 * Update from Maciej Izak, bug ID #33921
git-svn-id: trunk@39345 -
2018-06-29 20:43:21 +00:00

219 lines
7.8 KiB
ObjectPascal
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Generic types for NewPascal.org and FPC!
// Original version by keeper89.blogspot.com, 2011
// FPC version by Maciej Izak (hnb), 2014
program THashMapProject;
{$MODE DELPHI}
{$APPTYPE CONSOLE}
uses
SysUtils, Generics.Collections, Generics.Defaults;
type
TSubscriberInfo = record
Name, SName: string;
class function Create(const Name, SName: string): TSubscriberInfo; static;
function ToString: string;
end;
// Class containing handlers add / remove items in the dictionary
THashMapEventsHandler = class
public
class procedure OnKeyNotify(Sender: TObject; constref Item: string;
Action: TCollectionNotification);
class procedure OnValueNotify(Sender: TObject; constref Item: TSubscriberInfo;
Action: TCollectionNotification);
end;
class function TSubscriberInfo.Create(const Name,
SName: string): TSubscriberInfo;
begin
Result.Name := Name;
Result.SName := SName;
end;
function TSubscriberInfo.ToString: string;
begin
Result := Format('%s %s', [Name, SName]);
end;
// Function to generate the dictionary contents into a string
function PrintTelephoneDirectory(
TelephoneDirectory: THashMap<string, TSubscriberInfo>): string;
var
PhoneNumber: string;
begin
Result := Format('Content directory (%d):', [TelephoneDirectory.Count]);
for PhoneNumber in TelephoneDirectory.Keys do
Result := Result + Format(LineEnding + '%s: %s',
[PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]);
end;
// Handlers add / remove items dictionary
class procedure THashMapEventsHandler.OnKeyNotify(Sender: TObject;
constref Item: string; Action: TCollectionNotification);
begin
case Action of
cnAdded:
Writeln(Format('OnKeyNotify! Phone %s added!', [Item]));
cnRemoved:
Writeln(Format('OnKeyNotify! Number %s deleted!', [Item]));
end;
end;
class procedure THashMapEventsHandler.OnValueNotify(Sender: TObject;
constref Item: TSubscriberInfo; Action: TCollectionNotification);
begin
case Action of
cnAdded:
Writeln(Format('OnValueNotify! Subscriber %s added!', [Item.ToString]));
cnRemoved:
Writeln(Format('OnValueNotify! Subscriber %s deleted!', [Item.ToString]));
end;
end;
function CustomCompare(constref Left, Right: TPair<string, TSubscriberInfo>): Integer;
begin
// Comparable full first names, and then phones if necessary
Result := TCompare.&String(Left.Value.ToString, Right.Value.ToString);
if Result = 0 then
Result := TCompare.&String(Left.Key, Right.Key);
end;
var
// Declare the "dictionary"
// key is the telephone number which will be possible
// to determine information about the owner
TelephoneDirectory: THashMap<string, TSubscriberInfo>;
TTelephoneArray: array of TPair<string, TSubscriberInfo>;
TTelephoneArrayItem: TPair<string, TSubscriberInfo>;
PhoneNumber: string;
Subscriber: TSubscriberInfo;
begin
WriteLn('Working with THashMap - phonebook');
WriteLn;
// create a directory
// Constructor has several overloaded options which will
// enable the capacity of the container, a comparator for values
// or the initial data - we use the easiest option
TelephoneDirectory := THashMap<string, TSubscriberInfo>.Create;
// ---------------------------------------------------
// 1) Adding items to dictionary
// Add new users to the phonebook
TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Brad', 'Pitt'));
TelephoneDirectory.Add('9204444444', TSubscriberInfo.Create('Brad', 'Pitt'));
TelephoneDirectory.Add('9205555555', TSubscriberInfo.Create('Sandra', 'Bullock'));
// Adding a new subscriber if number already exist
TelephoneDirectory.AddOrSetValue('9204444444',
TSubscriberInfo.Create('Angelina', 'Jolie'));
// Print list
Writeln(PrintTelephoneDirectory(TelephoneDirectory));
// ---------------------------------------------------
// 2) Working with the elements
// Set the "capacity" of the dictionary according to the current number of elements
TelephoneDirectory.TrimExcess;
// Is there a key? - ContainsKey
if TelephoneDirectory.ContainsKey('9205555555') then
Writeln('Phone 9205555555 registered!');
// Is there a subscriber? - ContainsValue
Subscriber := TSubscriberInfo.Create('Sandra', 'Bullock');
if TelephoneDirectory.ContainsValue(Subscriber) then
Writeln(Format('%s is in the directory!', [Subscriber.ToString]));
// Try to get information via telephone. TryGetValue
if TelephoneDirectory.TryGetValue('9204444444', Subscriber) then
Writeln(Format('Number 9204444444 belongs to %s', [Subscriber.ToString]));
// Directly access by phone number
Writeln(Format('Phone 9201111111 subscribers: %s', [TelephoneDirectory['9201111111'].ToString]));
// Number of people in the directory
Writeln(Format('Total subscribers in the directory: %d', [TelephoneDirectory.Count]));
// ---------------------------------------------------
// 3) Delete items
// Schwarzenegger now will not be listed
TelephoneDirectory.Remove('9201111111');
// Completely clear the list
TelephoneDirectory.Clear;
// ---------------------------------------------------
// 4) Events add / remove values
//
// Events OnKeyNotify OnValueNotify are designed for "tracking"
// for adding / removing keys and values respectively
TelephoneDirectory.OnKeyNotify := THashMapEventsHandler.OnKeyNotify;
TelephoneDirectory.OnValueNotify := THashMapEventsHandler.OnValueNotify;
Writeln;
// Try events
TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
TelephoneDirectory['9202222222'] := TSubscriberInfo.Create('Monica', 'Bellucci');
TelephoneDirectory.Clear;
WriteLn;
TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Monica', 'Bellucci'));
TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Sylvester', 'Stallone'));
TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Bruce', 'Willis'));
WriteLn;
// Show keys (phones)
Writeln('Keys (phones):');
for PhoneNumber in TelephoneDirectory.Keys do
Writeln(PhoneNumber);
Writeln;
// Show values (subscribers)
Writeln('Values (subscribers):');
for Subscriber in TelephoneDirectory.Values do
Writeln(Subscriber.ToString);
Writeln;
// All together now
Writeln('Subscribers list with phones:');
for PhoneNumber in TelephoneDirectory.Keys do
Writeln(Format('%s: %s',
[PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]));
Writeln;
// In addition, we can "export" from the dictionary
// to TArray
// Sort the resulting array and display
TTelephoneArray := TelephoneDirectory.ToArray;
// partial specializations not allowed
// same for anonymous methods
//TArray.Sort<TPair<string, TSubscriberInfo>>(
// TTelephoneArray, TComparer<TPair<string, TSubscriberInfo>>.Construct(
// function (const Left, Right: TPair<string, TSubscriberInfo>): Integer
// begin
// // Comparable full first names, and then phones if necessary
// Result := CompareStr(Left.Value.ToString, Right.Value.ToString);
// if Result = 0 then
// Result := CompareStr(Left.Key, Right.Key);
// end));
TArrayHelper<TelephoneDirectory.TDictionaryPair>.Sort(
TTelephoneArray, TComparer<TelephoneDirectory.TDictionaryPair>.Construct(
CustomCompare));
// Print
Writeln('Sorted list of subscribers into TArray (by name, and eventually by phone):');
for TTelephoneArrayItem in TTelephoneArray do
Writeln(Format('%s: %s',
[TTelephoneArrayItem.Value.ToString, TTelephoneArrayItem.Key]));
Writeln;
FreeAndNil(TelephoneDirectory);
Readln;
end.