2
0

tobjectlistproject.lpr 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 TObjectListProject;
  5. {$MODE DELPHI}
  6. {$APPTYPE CONSOLE}
  7. uses
  8. SysUtils, Generics.Collections, Generics.Defaults, DateUtils;
  9. type
  10. TPlayer = class
  11. public
  12. Name, Team: string;
  13. BirthDay: TDateTime;
  14. NTeamGoals: Byte; // Number of goals for the national team
  15. constructor Create(const Name: string; BirthDay: TDateTime;
  16. const Team: string; NTeamGoals: Byte = 0);
  17. function ToString: string;
  18. end;
  19. // Class containing handlers add / remove list items
  20. TListEventsHandler = class
  21. public
  22. class procedure OnListChanged(Sender: TObject; constref Item: TPlayer;
  23. Action: TCollectionNotification);
  24. end;
  25. constructor TPlayer.Create(const Name: string; BirthDay: TDateTime;
  26. const Team: string; NTeamGoals: Byte);
  27. begin
  28. Self.Name := Name;
  29. Self.BirthDay := BirthDay;
  30. Self.Team := Team;
  31. Self.NTeamGoals := NTeamGoals;
  32. end;
  33. function TPlayer.ToString: string;
  34. begin
  35. Result := Format('%s - Age: %d Team: %s Goals: %d',
  36. [Name,
  37. DateUtils.YearsBetween(Date, BirthDay),
  38. Team, NTeamGoals])
  39. end;
  40. // Function sort descending goals for the national team
  41. function ComparePlayersByGoalsDecs(constref Player1, Player2: TPlayer): Integer;
  42. begin
  43. Result := TCompare.UInt8(Player2.NTeamGoals, Player1.NTeamGoals);
  44. end;
  45. class procedure TListEventsHandler.OnListChanged(Sender: TObject; constref Item: TPlayer;
  46. Action: TCollectionNotification);
  47. var
  48. Mes: string;
  49. begin
  50. // Unlike TDictionary we added Action = cnExtracted
  51. case Action of
  52. cnAdded:
  53. Mes := 'added to the list!';
  54. cnRemoved:
  55. Mes := 'removed from the list!';
  56. cnExtracted:
  57. Mes := 'extracted from the list!';
  58. end;
  59. Writeln(Format('Football player %s %s ', [Item.ToString, Mes]));
  60. end;
  61. var
  62. // Declare TObjectList as storage for TPlayer
  63. PlayersList: TObjectList<TPlayer>;
  64. Player: TPlayer;
  65. FoundIndex: PtrInt;
  66. begin
  67. WriteLn('Working with TObjectList - football manager');
  68. WriteLn;
  69. PlayersList := TObjectList<TPlayer>.Create;
  70. // ---------------------------------------------------
  71. // 1) Adding items
  72. PlayersList.Add(
  73. TPlayer.Create('Zinedine Zidane', EncodeDate(1972, 06, 23), 'France', 31));
  74. PlayersList.Add(
  75. TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44));
  76. PlayersList.Add(
  77. TPlayer.Create('Ronaldo', EncodeDate(1976, 09, 22), 'Brazil', 62));
  78. // Adding the specified position
  79. PlayersList.Insert(0,
  80. TPlayer.Create('Luis Figo', EncodeDate(1972, 11, 4), 'Portugal', 33));
  81. // Add a few players through InsertRange (AddRange works similarly)
  82. PlayersList.InsertRange(0,
  83. [TPlayer.Create('David Beckham', EncodeDate(1975, 05, 2), 'England', 17),
  84. TPlayer.Create('Alessandro Del Piero', EncodeDate(1974, 11, 9), 'Italy ', 27),
  85. TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44)]);
  86. Player := TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44);
  87. PlayersList.Add(Player);
  88. // ---------------------------------------------------
  89. // 2) Access and check the items
  90. // Is there a player in the list - Contains
  91. if PlayersList.Contains(Player) then
  92. Writeln('Raul is in the list!');
  93. // Player index and count of items in the list
  94. Writeln(Format('Raul is %d-th on the list of %d players.',
  95. [PlayersList.IndexOf(Player) + 1, PlayersList.Count]));
  96. // Index access
  97. Writeln(Format('1st in the list: %s', [PlayersList[0].ToString]));
  98. // The first player
  99. Writeln(Format('1st in the list: %s', [PlayersList.First.ToString]));
  100. // The last player
  101. Writeln(Format('Last in the list: %s', [PlayersList.Last.ToString]));
  102. // "Reverse" elements
  103. PlayersList.Reverse;
  104. Writeln('List items have been "reversed"');
  105. Writeln;
  106. // ---------------------------------------------------
  107. // 3) Moving and removing items
  108. // Changing places players in the list
  109. PlayersList.Exchange(0, 1);
  110. // Move back 1 player
  111. PlayersList.Move(1, 0);
  112. // Removes the element at index
  113. PlayersList.Delete(5);
  114. // Or a number of elements starting at index
  115. PlayersList.DeleteRange(5, 2);
  116. // Remove the item from the list, if the item
  117. // exists returns its index in the list
  118. Writeln(Format('Removed %d-st player', [PlayersList.Remove(Player) + 1]));
  119. // Extract and return the item, if there is no Player in the list then
  120. // Extract will return = nil, (anyway Raul is already removed via Remove)
  121. Player := PlayersList.Extract(Player);
  122. if Assigned(Player) then
  123. Writeln(Format('Extracted: %s', [Player.ToString]));
  124. // Clear the list completely
  125. PlayersList.Clear;
  126. Writeln;
  127. // ---------------------------------------------------
  128. // 4) Event OnNotify, sorting and searching
  129. PlayersList.OnNotify := TListEventsHandler.OnListChanged;
  130. PlayersList.Add(
  131. TPlayer.Create('Zinedine Zidane', EncodeDate(1972, 06, 23), 'France', 31));
  132. PlayersList.Add(
  133. TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44));
  134. PlayersList.Add(
  135. TPlayer.Create('Ronaldo', EncodeDate(1976, 09, 22), 'Brazil', 62));
  136. PlayersList.AddRange(
  137. [TPlayer.Create('David Beckham', EncodeDate(1975, 05, 2), 'England', 17),
  138. TPlayer.Create('Alessandro Del Piero', EncodeDate(1974, 11, 9), 'Italy ', 27),
  139. TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44)]);
  140. PlayersList.Remove(PlayersList.Last);
  141. Player := PlayersList.Extract(PlayersList[0]);
  142. PlayersList.Sort(TComparer<TPlayer>.Construct(ComparePlayersByGoalsDecs));
  143. Writeln;
  144. Writeln('Sorted list of players:');
  145. for Player in PlayersList do
  146. Writeln(Player.ToString);
  147. Writeln;
  148. // Find Ronaldo!
  149. // TArray BinarySearch requires sorted list
  150. // IndexOf does not require sorted list
  151. // but BinarySearch is usually faster
  152. Player := PlayersList[0];
  153. if PlayersList.BinarySearch(Player, FoundIndex,
  154. TComparer<TPlayer>.Construct(ComparePlayersByGoalsDecs)) then
  155. Writeln(Format('Ronaldo is in the sorted list at position %d', [FoundIndex + 1]));
  156. Writeln;
  157. // With the destruction of the list remove all elements
  158. // OnNotify show it
  159. FreeAndNil(PlayersList);
  160. Readln;
  161. end.