 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Pete Watts Guest
|
Posted: Tue Feb 10, 2004 4:02 pm Post subject: Index Records |
|
|
Hi
I use a record structure to hold data from a table,it looks like this:
type
TRecInfo = record
SiteName: string[30];
AppName: string[25];
SiteNum: string[6];
end;
var
Grec: array of TRecInfo;
I get data back from the record like this:
for i := Low(Grec) to High(Grec) do
begin
ShowMessage('Grec is: '+Grec[i].SiteName+' '+Grec[i].AppName+'
'+
Grec[i].SiteNum);
end;
Can anyone tell me how I may sort or index the record structure so
that the field "Sitename" is in order when I access the data.
Thanks
PW
|
|
| Back to top |
|
 |
Malte Persike Guest
|
Posted: Tue Feb 10, 2004 4:45 pm Post subject: Re: Index Records |
|
|
On Tue, 10 Feb 2004 16:02:03 +0000, Pete Watts <pwa334 (AT) aol (DOT) com> wrote:
....snip
| Quote: | Can anyone tell me how I may sort or index the record structure so
that the field "Sitename" is in order when I access the data.
|
Hi Pete,
you have to do it with a sort routine that does not compare the
entries of the Grec array but takes the .SiteName property as a
sorting key.
I once implemented a quicksort algorithm for a TList and copy/pasted
the modified code below. Compiling and working are not guaranteed but
I think you'll get the picture. Note that the quicksort is a recursive
type. There are non-recursive implementations which are easier to
understand and debug.
Kind regards,
Malte
--
// Quicksort: Sorts array A from item index L to R
// Result: Returns true if any sorting was necessary
function QuickSort(var A: TGrecArrayType; L, R: Integer): Boolean;
var
I, J: Integer;
P: string;
T: TRecInfo;
retval: Boolean;
begin
retval:= false;
repeat
I:= L;
J:= R;
P:= A[(L + R) shr 1].SiteName;
repeat
while (StrComp(PChar(A[I].SiteName), PChar(P))<0) do begin
inc(I);
end;
while (StrComp(PChar(A[I].SiteName), PChar(P))>0) do begin
dec(J);
end;
if (I <= J) then begin
T:= A[I];
A[I]:= A[J];
A[J]:= T;
inc(I);
dec(J);
retval:= true;
end;
until (I > J);
if (L < J) then begin
retval:= retval or QuickSort(A, L, J);
end;
L := I;
until (I >= R);
Result:= retval;
end;
---
The above e-mail address is not valid. To
contact me, please use my real e-mail address:
malte AT t DASH online DOT de
|
|
| Back to top |
|
 |
Harley Pebley Guest
|
Posted: Tue Feb 10, 2004 11:24 pm Post subject: Re: Index Records |
|
|
| Quote: | I use a record structure to hold data from a table,it looks like this:
type
TRecInfo = record
...
end;
var
Grec: array of TRecInfo;
Can anyone tell me how I may sort or index the record structure so
that the field "Sitename" is in order when I access the data.
|
Instead of storing the records in an array, use a TList, then sorting is a
matter of Sort(sortRecords) where:
function sortRecords(Item1, Item2: Pointer): Integer;
begin
result := CompareStr(TRecInfo(Item1).SiteName, TRecInfo(Item2).SiteName);
end;
HTH,
Harley Pebley
|
|
| Back to top |
|
 |
Malte Persike Guest
|
Posted: Wed Feb 11, 2004 3:54 am Post subject: Re: Index Records |
|
|
| Quote: | Instead of storing the records in an array, use a TList, then sorting is a
matter of Sort(sortRecords) where:
|
Question: Can plain record variables be stored in a TList?
To my knowledge a TList internally holds pointers to objects. A record
is not an object and thus not persistent, i. e. when the record
variable goes out of scope, any pointer to it will be invalid.
Pete would have to dynamically create instances of TRecInfo with
new/delete to make the TList concept functional.
Besides, I also would advocate using a TList - with TRecInfo as a
class, not a record. Sort of more OO-like.
Regards,
Malte
--
The above e-mail address is not valid. To
contact me, please use my real e-mail address:
malte AT t DASH online DOT de
|
|
| Back to top |
|
 |
Pete Watts Guest
|
Posted: Wed Feb 11, 2004 11:13 am Post subject: Re: Index Records |
|
|
On Tue, 10 Feb 2004 17:45:13 +0100, Malte Persike <me (AT) privacy (DOT) net>
wrote:
Many thanks,
PW
| Quote: | On Tue, 10 Feb 2004 16:02:03 +0000, Pete Watts <pwa334 (AT) aol (DOT) com> wrote:
Hi Pete,
you have to do it with a sort routine that does not compare the
entries of the Grec array but takes the .SiteName property as a
sorting key.
I once implemented a quicksort algorithm for a TList and copy/pasted
the modified code below. Compiling and working are not guaranteed but
I think you'll get the picture. Note that the quicksort is a recursive
type. There are non-recursive implementations which are easier to
understand and debug.
Kind regards,
Malte
|
|
|
| Back to top |
|
 |
Harley Pebley Guest
|
Posted: Wed Feb 11, 2004 6:38 pm Post subject: Re: Index Records |
|
|
| Quote: | Instead of storing the records in an array, use a TList, then sorting is a
matter of Sort(sortRecords) where:
Question: Can plain record variables be stored in a TList?
|
Yes.
| Quote: | To my knowledge a TList internally holds pointers to objects.
|
No. A TList holds pointers. Those pointers point to objects, records,
characters or anything else stored in memory. Or it could hold some other
data that fits in a pointer but isn't a pointer. E.g.:
var
someInteger: Integer;
....
someList.Add(Pointer(someInteger));
....
someInteger := Integer(someList.Items[0]);
| Quote: | A record is not an object and thus not persistent, i. e. when the record
variable goes out of scope, any pointer to it will be invalid.
|
Sure, thanks for stating that explictly for the OP. Scoping rules always
apply. One can't store a pointer to a local variable and expect that local
variable to still be valid outside the method. (Well, I guess it could be
expected, but there'll be AVs until the compiler forces a change of
expectations. :-)
| Quote: | Pete would have to dynamically create instances of TRecInfo with
new/delete to make the TList concept functional.
|
Yes. Or create a TRecInfoList class that wraps that function in its
Add/Delete methods.
| Quote: | Besides, I also would advocate using a TList - with TRecInfo as a
class, not a record. Sort of more OO-like.
|
Yes, that is another alternative; and typically records have methods that
operate on them which would then become methods of the object. But now
we're starting to digress into another topic. Yet another option would
be to use a TObjectList. In that case the sort method would cast the items
to the appropriate object type, rather than record type.
Regards,
Harley Pebley
|
|
| Back to top |
|
 |
Paul Guest
|
Posted: Thu Feb 12, 2004 11:19 am Post subject: Re: Index Records |
|
|
"Pete Watts" <pwa334 (AT) aol (DOT) com> wrote
| Quote: | Hi
Can anyone tell me how I may sort or index the record structure so
that the field "Sitename" is in order when I access the data.
Peter |
Here is a method of doing this
<---- Start Unit ----->
unit recInfo;
interface
uses
classes;
type
TSiteName = string[30];
TAppName = string[25];
TStieNum = string[6];
TRecInfo = record
SiteName : TSiteName;
AppName : TAppName;
SiteNum : TStieNum;
end;
TRecInfos = array of TRecInfo;
IRecInfoItterator = Interface
['{B821ECE8-A452-4198-A185-E8281A534073}']
procedure first;
procedure next;
function isDone
: boolean;
function currentItem
: TRecInfo;
end;
TRecInfoManager = class
private
fRecInfos : TRecInfos;
FSiteNameIdx : TList;
procedure updateSiteNameIndex
(
siteName : TSiteName;
recInfoIndex : integer
);
public
constructor create;
virtual;
destructor destroy;
override;
procedure add
(
siteName : TSiteName;
AppName : TAppName;
SiteNum : TStieNum
);
function siteNameIndex
: IRecInfoItterator;
end;
implementation
type
TRecInfoItterator = class(TInterfacedObject, IRecInfoItterator )
private
fRecInfos : TRecInfos;
fIndex : TList;
fCurrentItemIdx : integer;
procedure first;
procedure next;
function isDone
: boolean;
function currentItem
: TRecInfo;
public
constructor create
(
RecInfos : TRecInfos;
Index : TList
);
virtual;
end;
// -- TRecInfoItterator
// - private
procedure TRecInfoItterator.first;
begin
fCurrentItemIdx := 0;
end;
procedure TRecInfoItterator.next;
begin
assert( not isDone,
'Logic Error::TRecInfoItterator.next - isDone is true');
inc( fCurrentItemIdx );
end;
function TRecInfoItterator.isDone
: boolean;
begin
result := fCurrentItemIdx = fIndex.Count;
end;
function TRecInfoItterator.currentItem
: TRecInfo;
begin
result := fRecInfos[integer(fIndex.Items[ fCurrentItemIdx ])];
end;
// - public
constructor TRecInfoItterator.create
(
RecInfos : TRecInfos;
Index : TList
);
begin
inherited create;
fRecInfos := RecInfos;
fIndex := Index;
first;
end;
// -- TRecInfoManager
// - private
procedure TRecInfoManager.updateSiteNameIndex
(
siteName : TSiteName;
recInfoIndex : integer
);
var
indexUpdated : boolean;
siteIndexIndex : integer;
begin
indexUpdated := false;
siteIndexIndex := 0;
repeat
if siteIndexIndex = FSiteNameIdx.Count then begin
FSiteNameIdx.Add( pointer( recInfoIndex ));
indexUpdated := true;
end else if (siteName < fRecInfos[integer(FSiteNameIdx.Items[
siteIndexIndex ])].SiteName) then begin
FSiteNameIdx.Insert( siteIndexIndex, pointer( recInfoIndex ));
indexUpdated := true;
end;
inc( siteIndexIndex );
until indexUpdated;
end;
// - public
constructor TRecInfoManager.create;
begin
inherited create;
FSiteNameIdx := TList.create;
end;
destructor TRecInfoManager.destroy;
begin
setLength( fRecInfos, 0 );
FSiteNameIdx.Free;
inherited;
end;
procedure TRecInfoManager.add
(
siteName : TSiteName;
AppName : TAppName;
SiteNum : TStieNum
);
begin
setlength( fRecInfos, length( fRecInfos ) + 1);
fRecInfos[ high( fRecInfos )].SiteName := siteName;
fRecInfos[ high( fRecInfos )].AppName := AppName;
fRecInfos[ high( fRecInfos )].SiteNum := SiteNum;
updateSiteNameIndex( siteName, high( fRecInfos ));
end;
function TRecInfoManager.siteNameIndex
: IRecInfoItterator;
begin
result := TRecInfoItterator.create( fRecInfos, FSiteNameIdx );
end;
end.
<---- End Unit ----->
regards
Paul
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|