x
Solved

Sorting Array of records with multiple sort keys

Posted on 2004-03-31
Medium Priority
753 Views
I need a function that will sort an array of records, using multiple keys, i.e. similar to using
ORDER BY customer_no, Inv_date, ord_number in SQL.

The number of records in the array will not be very large, probably only several hundred maximum.

Any guidance will be greatly appreciated.

Alan
0
Question by:alanjbrown
• 3
• 2

LVL 27

Expert Comment

ID: 10730090
you may use a tlist or tstringlist as your record-container,
rather than an array, then u can use the customsort capability
of this objects.

meikl ;-)
0

LVL 1

Author Comment

ID: 10730992
Meikl

I think that I need some additional help. In  Delphi help I can't find any reference to  customsort. Is this available in Delphi 4?
An example using  multiple keys would be useful.

Alan
0

LVL 27

Accepted Solution

kretzschmar earned 1000 total points
ID: 10731444
well, a sample

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
fList : TList;
procedure DisplayList;
public
{ Public declarations }
end;

PToOrderRec = ^TToOrderRec;
TToOrderRec = record
customerName : String[100];
Customer_no  : Integer;
Inv_Date : TDateTime;
OrderNo  : Integer;
end;

var
Form1: TForm1;

implementation

{\$R *.dfm}

function RandomStr(ALen : Integer) : String;
var i : integer;
begin
result := '';
for i := 1 to ALen do
result := result + chr(random(26)+65);
end;

function RandomInt(Range : Integer) : Integer;
begin
result := Random(Range);
end;

//sort Customer_no, Inv_Date, OrderNo
function CustomSort(p1,p2 : pointer) : Integer;
var pa, pb : PToOrderRec;  //just to read it better
begin
pa := PToOrderRec(p1);
pb := PToOrderRec(p2);
result := 0;
if      pa^.Customer_no > pb^.Customer_no then
result := 1
else if pa^.Customer_no < pb^.Customer_no then
result := -1
else if pa^.Inv_Date > pb^.Inv_Date then
result := 1
else if pa^.Inv_Date < pb^.Inv_Date then
result := -1
else if pa^.OrderNo > pb^.OrderNo then
result := 1
else if pa^.OrderNo < pb^.OrderNo then
result := -1
else
result := 0;
end;

procedure TForm1.DisplayList;
var
i : integer;
s : string;
begin
for i := 0 to flist.Count-1 do
begin
s :=     PToOrderRec(fList[i])^.customerName + ' - ';
s := s + IntToStr(PToOrderRec(fList[i])^.Customer_no) + ' - ';
s := s + DateToStr(PToOrderRec(fList[i])^.Inv_Date) + ' - ';
s := s + IntToStr(PToOrderRec(fList[i])^.Orderno);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
p : PToOrderRec;
begin
//simulate record
for i := 1 to 100 do
begin
new(p);
p^.customerName := RandomStr(25);
p^.Customer_no := RandomInt(999999);
p^.Inv_Date := RandomInt(trunc(now));
p^.OrderNo := RandomInt(999999);
end;
//Output unsorted
DisplayList;
//sort
flist.Sort(CustomSort);
//Output sorted
DisplayList;
//free memory
for i := 0 to flist.Count-1 do
dispose(PToOrderRec(flist[i]));
flist.Clear;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
flist := TList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
flist.Free;
end;

end.

meikl ;-)
0

LVL 1

Author Comment

ID: 10731500

Alan
0

LVL 27

Expert Comment

ID: 10731527
hum, sorry,
just remove the variants part from the uses clause
(was introduced with delphi6)

meikl ;-)
0

Featured Post

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.