thashmapproject.lpr 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Generic types for NewPascal.org and FPC!
  2. // Original version by keeper89.blogspot.com, 2011
  3. // FPC version by Maciej Izak (hnb), 2014
  4. program THashMapProject;
  5. {$MODE DELPHI}
  6. {$APPTYPE CONSOLE}
  7. uses
  8. SysUtils, Generics.Collections, Generics.Defaults;
  9. type
  10. TSubscriberInfo = record
  11. Name, SName: string;
  12. class function Create(const Name, SName: string): TSubscriberInfo; static;
  13. function ToString: string;
  14. end;
  15. // Class containing handlers add / remove items in the dictionary
  16. THashMapEventsHandler = class
  17. public
  18. class procedure OnKeyNotify(Sender: TObject; constref Item: string;
  19. Action: TCollectionNotification);
  20. class procedure OnValueNotify(Sender: TObject; constref Item: TSubscriberInfo;
  21. Action: TCollectionNotification);
  22. end;
  23. class function TSubscriberInfo.Create(const Name,
  24. SName: string): TSubscriberInfo;
  25. begin
  26. Result.Name := Name;
  27. Result.SName := SName;
  28. end;
  29. function TSubscriberInfo.ToString: string;
  30. begin
  31. Result := Format('%s %s', [Name, SName]);
  32. end;
  33. // Function to generate the dictionary contents into a string
  34. function PrintTelephoneDirectory(
  35. TelephoneDirectory: THashMap<string, TSubscriberInfo>): string;
  36. var
  37. PhoneNumber: string;
  38. begin
  39. Result := Format('Content directory (%d):', [TelephoneDirectory.Count]);
  40. for PhoneNumber in TelephoneDirectory.Keys do
  41. Result := Result + Format(LineEnding + '%s: %s',
  42. [PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]);
  43. end;
  44. // Handlers add / remove items dictionary
  45. class procedure THashMapEventsHandler.OnKeyNotify(Sender: TObject;
  46. constref Item: string; Action: TCollectionNotification);
  47. begin
  48. case Action of
  49. cnAdded:
  50. Writeln(Format('OnKeyNotify! Phone %s added!', [Item]));
  51. cnRemoved:
  52. Writeln(Format('OnKeyNotify! Number %s deleted!', [Item]));
  53. end;
  54. end;
  55. class procedure THashMapEventsHandler.OnValueNotify(Sender: TObject;
  56. constref Item: TSubscriberInfo; Action: TCollectionNotification);
  57. begin
  58. case Action of
  59. cnAdded:
  60. Writeln(Format('OnValueNotify! Subscriber %s added!', [Item.ToString]));
  61. cnRemoved:
  62. Writeln(Format('OnValueNotify! Subscriber %s deleted!', [Item.ToString]));
  63. end;
  64. end;
  65. function CustomCompare(constref Left, Right: TPair<string, TSubscriberInfo>): Integer;
  66. begin
  67. // Comparable full first names, and then phones if necessary
  68. Result := TCompare.&String(Left.Value.ToString, Right.Value.ToString);
  69. if Result = 0 then
  70. Result := TCompare.&String(Left.Key, Right.Key);
  71. end;
  72. var
  73. // Declare the "dictionary"
  74. // key is the telephone number which will be possible
  75. // to determine information about the owner
  76. TelephoneDirectory: THashMap<string, TSubscriberInfo>;
  77. TTelephoneArray: array of TPair<string, TSubscriberInfo>;
  78. TTelephoneArrayItem: TPair<string, TSubscriberInfo>;
  79. PhoneNumber: string;
  80. Subscriber: TSubscriberInfo;
  81. begin
  82. WriteLn('Working with THashMap - phonebook');
  83. WriteLn;
  84. // create a directory
  85. // Constructor has several overloaded options which will
  86. // enable the capacity of the container, a comparator for values
  87. // or the initial data - we use the easiest option
  88. TelephoneDirectory := THashMap<string, TSubscriberInfo>.Create;
  89. // ---------------------------------------------------
  90. // 1) Adding items to dictionary
  91. // Add new users to the phonebook
  92. TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
  93. TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
  94. TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Brad', 'Pitt'));
  95. TelephoneDirectory.Add('9204444444', TSubscriberInfo.Create('Brad', 'Pitt'));
  96. TelephoneDirectory.Add('9205555555', TSubscriberInfo.Create('Sandra', 'Bullock'));
  97. // Adding a new subscriber if number already exist
  98. TelephoneDirectory.AddOrSetValue('9204444444',
  99. TSubscriberInfo.Create('Angelina', 'Jolie'));
  100. // Print list
  101. Writeln(PrintTelephoneDirectory(TelephoneDirectory));
  102. // ---------------------------------------------------
  103. // 2) Working with the elements
  104. // Set the "capacity" of the dictionary according to the current number of elements
  105. TelephoneDirectory.TrimExcess;
  106. // Is there a key? - ContainsKey
  107. if TelephoneDirectory.ContainsKey('9205555555') then
  108. Writeln('Phone 9205555555 registered!');
  109. // Is there a subscriber? - ContainsValue
  110. Subscriber := TSubscriberInfo.Create('Sandra', 'Bullock');
  111. if TelephoneDirectory.ContainsValue(Subscriber) then
  112. Writeln(Format('%s is in the directory!', [Subscriber.ToString]));
  113. // Try to get information via telephone. TryGetValue
  114. if TelephoneDirectory.TryGetValue('9204444444', Subscriber) then
  115. Writeln(Format('Number 9204444444 belongs to %s', [Subscriber.ToString]));
  116. // Directly access by phone number
  117. Writeln(Format('Phone 9201111111 subscribers: %s', [TelephoneDirectory['9201111111'].ToString]));
  118. // Number of people in the directory
  119. Writeln(Format('Total subscribers in the directory: %d', [TelephoneDirectory.Count]));
  120. // ---------------------------------------------------
  121. // 3) Delete items
  122. // Schwarzenegger now will not be listed
  123. TelephoneDirectory.Remove('9201111111');
  124. // Completely clear the list
  125. TelephoneDirectory.Clear;
  126. // ---------------------------------------------------
  127. // 4) Events add / remove values
  128. //
  129. // Events OnKeyNotify OnValueNotify are designed for "tracking"
  130. // for adding / removing keys and values ​​respectively
  131. TelephoneDirectory.OnKeyNotify := THashMapEventsHandler.OnKeyNotify;
  132. TelephoneDirectory.OnValueNotify := THashMapEventsHandler.OnValueNotify;
  133. Writeln;
  134. // Try events
  135. TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
  136. TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
  137. TelephoneDirectory['9202222222'] := TSubscriberInfo.Create('Monica', 'Bellucci');
  138. TelephoneDirectory.Clear;
  139. WriteLn;
  140. TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Monica', 'Bellucci'));
  141. TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Sylvester', 'Stallone'));
  142. TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Bruce', 'Willis'));
  143. WriteLn;
  144. // Show keys (phones)
  145. Writeln('Keys (phones):');
  146. for PhoneNumber in TelephoneDirectory.Keys do
  147. Writeln(PhoneNumber);
  148. Writeln;
  149. // Show values ​​(subscribers)
  150. Writeln('Values (subscribers):');
  151. for Subscriber in TelephoneDirectory.Values do
  152. Writeln(Subscriber.ToString);
  153. Writeln;
  154. // All together now
  155. Writeln('Subscribers list with phones:');
  156. for PhoneNumber in TelephoneDirectory.Keys do
  157. Writeln(Format('%s: %s',
  158. [PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]));
  159. Writeln;
  160. // In addition, we can "export" from the dictionary
  161. // to TArray
  162. // Sort the resulting array and display
  163. TTelephoneArray := TelephoneDirectory.ToArray;
  164. // partial specializations not allowed
  165. // same for anonymous methods
  166. //TArray.Sort<TPair<string, TSubscriberInfo>>(
  167. // TTelephoneArray, TComparer<TPair<string, TSubscriberInfo>>.Construct(
  168. // function (const Left, Right: TPair<string, TSubscriberInfo>): Integer
  169. // begin
  170. // // Comparable full first names, and then phones if necessary
  171. // Result := CompareStr(Left.Value.ToString, Right.Value.ToString);
  172. // if Result = 0 then
  173. // Result := CompareStr(Left.Key, Right.Key);
  174. // end));
  175. TArrayHelper<TelephoneDirectory.TDictionaryPair>.Sort(
  176. TTelephoneArray, TComparer<TelephoneDirectory.TDictionaryPair>.Construct(
  177. CustomCompare));
  178. // Print
  179. Writeln('Sorted list of subscribers into TArray (by name, and eventually by phone):');
  180. for TTelephoneArrayItem in TTelephoneArray do
  181. Writeln(Format('%s: %s',
  182. [TTelephoneArrayItem.Value.ToString, TTelephoneArrayItem.Key]));
  183. Writeln;
  184. FreeAndNil(TelephoneDirectory);
  185. Readln;
  186. end.