fpc/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpr
michael d4f2a593d4 * Update from Maciej Izak, bug ID #33921
git-svn-id: trunk@39345 -
2018-06-29 20:43:21 +00:00

195 lines
6.1 KiB
ObjectPascal

// Generic types for NewPascal.org and FPC!
// 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.