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