program SortNestedStructs;
{$mode objfpc}{$H+}{$MODESWITCH ADVANCEDRECORDS}{$WARN 6058 OFF}{$WARN 5024 OFF}
uses
SysUtils, Generics.Collections, Generics.Defaults;
type
TAddress = record
City: string;
ZipCode: Integer;
end;
TPerson = record
Name: string;
Age: Integer;
Address: TAddress;
end;
TPersonList = specialize TList<TPerson>;
TPersonComparer = class(TInterfacedObject, specialize IComparer<TPerson>)
public
function Compare(constref Left, Right: TPerson): Integer;
end;
{ TPersonComparer }
function TPersonComparer.Compare(constref Left, Right: TPerson): Integer;
begin
// Primary Sort: City (Ascending)
Result := CompareText(Left.Address.City, Right.Address.City);
if Result <> 0 then Exit;
// Secondary Sort: ZipCode (Ascending)
Result := Left.Address.ZipCode - Right.Address.ZipCode;
if Result <> 0 then Exit;
// Tertiary Sort: Age (Ascending) - Fixes tie-breaker order
Result := Left.Age - Right.Age;
end;
var
People: TPersonList;
P: TPerson;
Person: TPerson;
Comparer: specialize IComparer<TPerson>;
begin
People := TPersonList.Create;
Comparer := TPersonComparer.Create;
try
// Add sample data
Person.Name := 'Alice'; Person.Age := 35; Person.Address.City := 'New York'; Person.Address.ZipCode := 8001;
People.Add(Person);
Person.Name := 'Bob'; Person.Age := 45; Person.Address.City := 'Boston'; Person.Address.ZipCode := 2108;
People.Add(Person);
Person.Name := 'Charlie'; Person.Age := 25; Person.Address.City := 'Austin'; Person.Address.ZipCode := 14006;
People.Add(Person);
Person.Name := 'Diana'; Person.Age := 30; Person.Address.City := 'New York'; Person.Address.ZipCode := 10001;
People.Add(Person);
Person.Name := 'Eve'; Person.Age := 28; Person.Address.City := 'Austin'; Person.Address.ZipCode := 14006;
People.Add(Person);
// Sort list
People.Sort(Comparer);
// Output results
for P in People do
WriteLn(Format('%-8s | Age: %d | City: %-8s | Zip: %d',
[P.Name, P.Age, P.Address.City, P.Address.ZipCode]));
finally
Comparer := nil;
People.Free;
end;
end.
{
run:
Charlie | Age: 25 | City: Austin | Zip: 14006
Eve | Age: 28 | City: Austin | Zip: 14006
Bob | Age: 45 | City: Boston | Zip: 2108
Alice | Age: 35 | City: New York | Zip: 8001
Diana | Age: 30 | City: New York | Zip: 10001
}