File: THashMapProject.lpr

package info (click to toggle)
lazarus 2.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 214,460 kB
  • sloc: pascal: 1,862,622; xml: 265,709; cpp: 56,595; sh: 3,008; java: 609; makefile: 535; perl: 297; sql: 222; ansic: 137
file content (218 lines) | stat: -rw-r--r-- 7,945 bytes parent folder | download | duplicates (2)
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.