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
|
// Generic types for FreeSparta.com and FreePascal!
// Original version by keeper89.blogspot.com, 2011
// FPC version by Maciej Izak (hnb), 2014
program TObjectListProject;
{$MODE DELPHI}
{$APPTYPE CONSOLE}
uses
SysUtils, Generics.Collections, Generics.Defaults, DateUtils;
type
TPlayer = class
public
Name, Team: string;
BirthDay: TDateTime;
NTeamGoals: Byte; // Number of goals for the national team
constructor Create(const Name: string; BirthDay: TDateTime;
const Team: string; NTeamGoals: Byte = 0);
function ToString: string;
end;
// Class containing handlers add / remove list items
TListEventsHandler = class
public
class procedure OnListChanged(Sender: TObject; constref Item: TPlayer;
Action: TCollectionNotification);
end;
constructor TPlayer.Create(const Name: string; BirthDay: TDateTime;
const Team: string; NTeamGoals: Byte);
begin
Self.Name := Name;
Self.BirthDay := BirthDay;
Self.Team := Team;
Self.NTeamGoals := NTeamGoals;
end;
function TPlayer.ToString: string;
begin
Result := Format('%s - Age: %d Team: %s Goals: %d',
[Name,
DateUtils.YearsBetween(Date, BirthDay),
Team, NTeamGoals])
end;
// Function sort descending goals for the national team
function ComparePlayersByGoalsDecs(constref Player1, Player2: TPlayer): Integer;
begin
Result := TCompare.UInt8(Player2.NTeamGoals, Player1.NTeamGoals);
end;
class procedure TListEventsHandler.OnListChanged(Sender: TObject; constref Item: TPlayer;
Action: TCollectionNotification);
var
Mes: string;
begin
// Unlike TDictionary we added Action = cnExtracted
case Action of
cnAdded:
Mes := 'added to the list!';
cnRemoved:
Mes := 'removed from the list!';
cnExtracted:
Mes := 'extracted from the list!';
end;
Writeln(Format('Football player %s %s ', [Item.ToString, Mes]));
end;
var
// Declare TObjectList as storage for TPlayer
PlayersList: TObjectList<TPlayer>;
Player: TPlayer;
FoundIndex: PtrInt;
begin
WriteLn('Working with TObjectList - football manager');
WriteLn;
PlayersList := TObjectList<TPlayer>.Create;
// ---------------------------------------------------
// 1) Adding items
PlayersList.Add(
TPlayer.Create('Zinedine Zidane', EncodeDate(1972, 06, 23), 'France', 31));
PlayersList.Add(
TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44));
PlayersList.Add(
TPlayer.Create('Ronaldo', EncodeDate(1976, 09, 22), 'Brazil', 62));
// Adding the specified position
PlayersList.Insert(0,
TPlayer.Create('Luis Figo', EncodeDate(1972, 11, 4), 'Portugal', 33));
// Add a few players through InsertRange (AddRange works similarly)
PlayersList.InsertRange(0,
[TPlayer.Create('David Beckham', EncodeDate(1975, 05, 2), 'England', 17),
TPlayer.Create('Alessandro Del Piero', EncodeDate(1974, 11, 9), 'Italy ', 27),
TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44)]);
Player := TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44);
PlayersList.Add(Player);
// ---------------------------------------------------
// 2) Access and check the items
// Is there a player in the list - Contains
if PlayersList.Contains(Player) then
Writeln('Raul is in the list!');
// Player index and count of items in the list
Writeln(Format('Raul is %d-th on the list of %d players.',
[PlayersList.IndexOf(Player) + 1, PlayersList.Count]));
// Index access
Writeln(Format('1st in the list: %s', [PlayersList[0].ToString]));
// The first player
Writeln(Format('1st in the list: %s', [PlayersList.First.ToString]));
// The last player
Writeln(Format('Last in the list: %s', [PlayersList.Last.ToString]));
// "Reverse" elements
PlayersList.Reverse;
Writeln('List items have been "reversed"');
Writeln;
// ---------------------------------------------------
// 3) Moving and removing items
// Changing places players in the list
PlayersList.Exchange(0, 1);
// Move back 1 player
PlayersList.Move(1, 0);
// Removes the element at index
PlayersList.Delete(5);
// Or a number of elements starting at index
PlayersList.DeleteRange(5, 2);
// Remove the item from the list, if the item
// exists returns its index in the list
Writeln(Format('Removed %d-st player', [PlayersList.Remove(Player) + 1]));
// Extract and return the item, if there is no Player in the list then
// Extract will return = nil, (anyway Raul is already removed via Remove)
Player := PlayersList.Extract(Player);
if Assigned(Player) then
Writeln(Format('Extracted: %s', [Player.ToString]));
// Clear the list completely
PlayersList.Clear;
Writeln;
// ---------------------------------------------------
// 4) Event OnNotify, sorting and searching
PlayersList.OnNotify := TListEventsHandler.OnListChanged;
PlayersList.Add(
TPlayer.Create('Zinedine Zidane', EncodeDate(1972, 06, 23), 'France', 31));
PlayersList.Add(
TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44));
PlayersList.Add(
TPlayer.Create('Ronaldo', EncodeDate(1976, 09, 22), 'Brazil', 62));
PlayersList.AddRange(
[TPlayer.Create('David Beckham', EncodeDate(1975, 05, 2), 'England', 17),
TPlayer.Create('Alessandro Del Piero', EncodeDate(1974, 11, 9), 'Italy ', 27),
TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44)]);
PlayersList.Remove(PlayersList.Last);
Player := PlayersList.Extract(PlayersList[0]);
PlayersList.Sort(TComparer<TPlayer>.Construct(ComparePlayersByGoalsDecs));
Writeln;
Writeln('Sorted list of players:');
for Player in PlayersList do
Writeln(Player.ToString);
Writeln;
// Find Ronaldo!
// TArray BinarySearch requires sorted list
// IndexOf does not require sorted list
// but BinarySearch is usually faster
Player := PlayersList[0];
if PlayersList.BinarySearch(Player, FoundIndex,
TComparer<TPlayer>.Construct(ComparePlayersByGoalsDecs)) then
Writeln(Format('Ronaldo is in the sorted list at position %d', [FoundIndex + 1]));
Writeln;
// With the destruction of the list remove all elements
// OnNotify show it
FreeAndNil(PlayersList);
Readln;
end.
|