1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
// Generic types for FreeSparta.com and FreePascal!
// 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.
|