Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Sort File paths by file creation date

874 views
Skip to first unread message

Alex Schulz

unread,
Mar 18, 2003, 5:23:52 PM3/18/03
to
Hi,

I have an array of records each of 2 fields: Filepath, a string and
CreationDate, TDateTime. I want to sort the array in ascending order
on the CreationDate field. Can anyone shed any light on how to do
this.

Thanks
Alex

Val Krzyzaniak

unread,
Mar 18, 2003, 6:43:16 PM3/18/03
to
Ever hear of a tStringList? This is too easy. Please look it up and continue
youe Delphi 101 homework assignment.
Val

"Alex Schulz" <alex....@superweb.ca> wrote in message
news:k94f7vk7hme3srk12...@4ax.com...

Alex Schulz

unread,
Mar 18, 2003, 9:11:27 PM3/18/03
to
On Tue, 18 Mar 2003 15:43:16 -0800, "Val Krzyzaniak"
<shar...@hotmail.com> wrote:

Look, if you don't want to help don't, but don't make stupid remarks.
I have just come to Delphi from Vb and can use some help rewriting an
app I already wrote in VB in Delphi. Unlike yourself, I was not born
with an intimate knowledge of every programing language under the sun.
As for your suggestion, I don't see how a stringlist which holds a
single list of strings, can help me sort an array of records
containing a string and a TDateTime field.

Terry Russell

unread,
Mar 18, 2003, 11:10:03 PM3/18/03
to
"Alex Schulz" <alex....@superweb.ca> wrote in message
news:k94f7vk7hme3srk12...@4ax.com...

add record pointers to a tlist

call list.sort and supply an appropriate comparer function
the pointers get sorted , then reload the array if necessary
or just use the list index to pick from the array


you could look at classes.pas for quicksort function code


tstringlist can have an object associated with each entry and has
a virtual sort method, exchanged strings take their object with them
ie initially store your string+object(dates) into a class you derived
from Tstringlist

Depends on your needs after sorting.


Terry Russell

unread,
Mar 18, 2003, 11:21:45 PM3/18/03
to
"Terry Russell" <troc...@optusnet.com.au> wrote in message
news:3e77edef$0$11662$afc3...@news.optusnet.com.au...

>
> you could look at classes.pas for quicksort function code

also demo\threads\sortthds.pas


AlanGLLoyd

unread,
Mar 19, 2003, 2:33:14 AM3/19/03
to
In article <k94f7vk7hme3srk12...@4ax.com>, Alex Schulz
<alex....@superweb.ca> writes:

This is a snippet of a similar task I had. There are four differences from your
requirement ...

1 I put the files (with a certain extension) into a TStringList.

2 I used a datetime value from within the file (not the file date) - a
TWaveFile is one of my object classes to do that

3 I sorted on the minute count of the TDateTime value (ie minutes from 31 Dec
1899) because the storage needs an integer. This was near enough for me.

4 I sorted it with my code.

{put filenames in strings, file date in minutes in objects}
{... get list of files in strings}
SL := TStringList.Create;
if FindFirst(PathName + '\*.' + LexWaveExt, 0, SrchRec) = Success then begin
repeat
SL.Add(PathName + '\' + SrchRec.Name);
until FindNext(SrchRec) <> Success;
FindClose(SrchRec);
end;
{... get dict time (minutes) in objects}
for i := 0 to SL.Count - 1 do begin
WF := TWaveFile.CreateOpen(SL.Strings[i]);
SL.Objects[i] := TObject(trunc(WF.DictData.DateTime2 * 24 * 60)); // date
as minutes
WF.Free;
end;
{... sort list on dict time in Objects}
repeat {until ListSorted}
ListSorted := true;
with SL do
for i := 0 to Count - 2 do
if integer(Objects[i]) < integer(Objects[i + 1]) then begin
{i is earlier (older) than i+1, so swap to get earliest at end}
Exchange(i, i + 1);
ListSorted := false;
end;
{end; for i := 0 to Count - 2}
{end; with SL}
until ListSorted;
{list is now sorted on dict age, earliest at top}

You can (if you don't already) use FileTimeToDateTime(FileAge(filepathname)) to
get the file dates into a TDateTime value.

Alan Lloyd
alang...@aol.com

Alex Schulz

unread,
Mar 19, 2003, 11:28:36 AM3/19/03
to
Thanks to all who replied.
Thie following is a trial run for the method (TList) that I decided
on.

unit Unit1;

interface

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

type
pFileInfo = ^TFileInfo;
TFileInfo = record
Name : string;
Date : TDateTime;
end;
type
TForm1 = class(TForm)
ListBox1: TListBox;
btnExec: TButton;
FileListBox1: TFileListBox; // hidden on form
procedure btnExecClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
function CompareDates(Item1, Item2: Pointer): Integer;
begin
if pFileInfo(Item1)^.Date < pFileInfo(Item2)^.Date then
result := -1
else if pFileInfo(Item1)^.Date = pFileInfo(Item2)^.Date then
result := 0
else
result := 1;
end;

procedure TForm1.btnExecClick(Sender: TObject);
const PATH = 'C:\Documents and Settings\Alex Schulz\My Documents\My
Pictures\Cars\';
var
Info : pFileInfo;
FileList : TList;
ix : integer;
s : String;
begin
FileList := TList.Create;
// set the hiddne filelistbox to the test path
FileListBox1.Directory := PATH;
try
// add the file names and dates to the list
// for each file in the filelistbox
for ix := 0 to (FileListBox1.Count -1) do begin
s := FileListBox1.Items[ix];
New(Info);
Info^.Name := s;
Info^.Date := FileDateToDateTime(FileAge(Path + s));
FileList.Add(Info);
end;
// sort the results
FileList.Sort(CompareDates);
// show results in the listbox on the form
for ix := 0 to (FileList.Count - 1) do begin
Info := FileList.Items[ix];
ListBox1.AddItem(Info^.Name, nil);
end;
// cleanup
for ix := 0 to (FileList.Count - 1) do begin
Info := FileList.Items[ix];
Dispose(Info);
end;
finally
FileList.Free;
end;
end;

end.

J French

unread,
Mar 19, 2003, 12:20:52 PM3/19/03
to
On Tue, 18 Mar 2003 22:41:27 -0330, Alex Schulz
<alex....@superweb.ca> wrote:

>On Tue, 18 Mar 2003 15:43:16 -0800, "Val Krzyzaniak"
><shar...@hotmail.com> wrote:
>
>Look, if you don't want to help don't, but don't make stupid remarks.
>I have just come to Delphi from Vb and can use some help rewriting an
>app I already wrote in VB in Delphi. Unlike yourself, I was not born
>with an intimate knowledge of every programing language under the sun.
>As for your suggestion, I don't see how a stringlist which holds a
>single list of strings, can help me sort an array of records
>containing a string and a TDateTime field.
>

It sounds as if you have an Array of Records
(or should have - they are just like VB's UDTs)

You then need an array of pointers to each of the records
( in VB an array of Longs containing 1,2,3,4 ... )

You then need to sort the pointers

Note: TDateTime is the same as VB's Date type
- it is a Double (Real) in drag

Here is a Shell Sort example :-

unit Unit1;

// USSort Demonstration - 26/5/01 J French

interface

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

Type
TIsGreater = Function( Const Item1, Item2:Integer):Boolean;
TSwap = Procedure( Const Item1, Item2:Integer);

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);


private
{ Private declarations }
public
{ Public declarations }
end;

Procedure USSort(Const Min, Max:Integer; IsGreater:TIsGreater;
Swap:TSwap);Forward;
var
Form1: TForm1;

implementation

{$R *.DFM}
Var
I : Array Of Integer ;

{Callback for Compare}
Function MyIsGreater( Const Item1, Item2:Integer ):Boolean;
Begin
Result := I[ Item1 ] > I[ Item2 ] ;
End; {MyIsGreater}

{Callback for Swap}
Procedure MySwap( Const Item1, Item2:Integer );
Var
H : Integer ;
Begin
H := I[ Item2 ] ;
I[ Item2 ] := I[ Item1 ] ;
I[ Item1 ] := H ;
End; {MySwap }

{Demonstration of USSort }
procedure TForm1.Button1Click(Sender: TObject);
Var
L9, Min, Max : Integer;
GoodFlag, BadFlag : Integer ;
begin

Min := 0 ;
Max := 1000 ;
// Set up the Integer Array
SetLength( I, Max ) ;
// Set reverse sort order
For L9 := Min To Max Do
I[L9] := Max - L9 ;

USSort( Min, Max, @MyIsGreater, @MySwap ) ;

// Now Check the Sorting
GoodFlag := 0 ;
BadFlag := 0 ;
For L9 := Min + 1 To Max Do
If I[L9] <> I[L9-1] + 1 Then
Begin
ShowMessage( 'Error ' + IntToStr( L9 ) ) ;
Inc( BadFlag ) ;
Break;
End
Else
Inc( GoodFlag ) ;

ShowMessage( 'Completed '
+ IntToStr( GoodFlag )
+ ' ' + IntToStr( BadFlag )
) ;
End;

{ #####################################################
Sort Utility with Callback for Compare and Swap
Method : Shell Sort
Min must be >= 0
Max must be >= Min
}
Procedure USSort(Const Min, Max:Integer; IsGreater:TIsGreater;
Swap:TSwap);
Var
L9, L8, Gap : Integer;
Begin

Gap := (Max - Min + 1) Div 2 + 1 ;
While Gap > 0 Do
Begin
For L9 := Min To Max - Gap Do
Begin
L8 := L9 ;
While L8 >= Min Do
Begin
If IsGreater(L8,L8 + Gap) Then
Swap( L8, L8 + Gap )
Else
L8 := Min - 1 ;
L8 := L8 - Gap ;
End; {While}
End; {For}
Gap := Gap Div 2;
End; {While}
End; {USSort}

end.

Dr John Stockton

unread,
Mar 19, 2003, 6:34:50 AM3/19/03
to
JRS: In article <20030319023314...@mb-fu.aol.com>, seen in
news:alt.comp.lang.borland-delphi, AlanGLLoyd <alang...@aol.com>
posted at Wed, 19 Mar 2003 07:33:14 :-

>
>3 I sorted on the minute count of the TDateTime value (ie minutes from 31 Dec
>1899) because the storage needs an integer. This was near enough for me.

from 30 Dec 1899 00:00:00 local time.

--
© John Stockton, Surrey, UK. j...@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036)
Do not Mail News to me. Before a reply, quote with ">" or "> " (SonOfRFC1036)

J French

unread,
Mar 20, 2003, 2:50:59 AM3/20/03
to
Hmm...

If you are using D4 or above, then I suggest that you look into
Dynamic Arrays.
In your case you *know* how many records you have, so you only have
one memory allocation - via SetLength()
- which has to speed things up.

Also using FindFirst instead of a FileListbox is a bit more direct, as
it saves (effectively) scanning the directory twice

Alex Schulz

unread,
Mar 20, 2003, 4:56:25 PM3/20/03
to
Actually I will stick with the TList and not bother iwth an array at
all. I will indeed be using FindFirst to populate the list. As I said,
this was only a test program. The actual application searches a number
of folders for AutoCAD drawings matching a specific filename criteria,
so I don't really know how many files I will have in a given search

Speed of operation is not a real issue here, getting the app up and
running is.

The TList seems to be ideal for this.

Once again, thanks to all for your suggestions.l

J French

unread,
Mar 21, 2003, 3:23:19 AM3/21/03
to
On Thu, 20 Mar 2003 18:26:25 -0330, Alex Schulz
<alex....@superweb.ca> wrote:

>Actually I will stick with the TList and not bother iwth an array at
>all. I will indeed be using FindFirst to populate the list. As I said,
>this was only a test program. The actual application searches a number
>of folders for AutoCAD drawings matching a specific filename criteria,
>so I don't really know how many files I will have in a given search
>
>Speed of operation is not a real issue here, getting the app up and
>running is.
>
>The TList seems to be ideal for this.
>

Fair enough

However, you should be aware that with Dynamic Arrays, SetLength() is
the Delphi equivalent of VB's Redim Preserve

It enables one to allocate contiguous records without using 'New' and
de-allocate them without using 'Dispose'

Alex Schulz

unread,
Mar 21, 2003, 9:38:33 AM3/21/03
to
Thanks for the info. People like you make the transition from VB to
Delphi that much easier.

Terry Russell

unread,
Mar 21, 2003, 11:51:22 AM3/21/03
to
"Alex Schulz" <alex....@superweb.ca> wrote in message
news:vddk7vs2aqmk4t9d4...@4ax.com...

> Actually I will stick with the TList and not bother iwth an array at
> all. I will indeed be using FindFirst to populate the list. As I said,
> this was only a test program. The actual application searches a number
> of folders for AutoCAD drawings matching a specific filename criteria,
> so I don't really know how many files I will have in a given search
>
> Speed of operation is not a real issue here, getting the app up and
> running is.
>
> The TList seems to be ideal for this.


Using a tlist/tstringlist/etc instead of arrays often comes down to only
between 2 and 4 times access overhead compared to an array.
Better overhead if you need to move/insert/delete elements. e.g. sort

If you spend significant time manipulating the data then that access time
difference is correspondingly less significant.
List code that works for nil,1, and 2 record should work until memory
limits,
usually has much simpler code, thus fewer bugs.
e.g. List objects already have all those little helper/cursor variables
maintained
you would have to write code for.

By the time arrays would be much more efficient you find managing arrays
of many megabytes to be much more work. Chicken eats egg.
The possibility of thrashing memory depending on access pattern
can be a factor against using lists, along with much larger memory
requirements compared to arrays for very small records.

The disk find operations would be the major bottleneck here ,
by a factor of 1000 and more.

J French

unread,
Mar 22, 2003, 2:16:03 AM3/22/03
to
On Fri, 21 Mar 2003 11:08:33 -0330, Alex Schulz
<alex....@superweb.ca> wrote:

>Thanks for the info. People like you make the transition from VB to
>Delphi that much easier.
>

The transition is not that bad
- mostly it is understanding the 'Delphi way'
- and that is not necessarily the Pascal way

One small thing that helped me a lot when it 'clicked', is to rigidly
stick to 'pure' Delphi formatting
- for some time I tried to mimic VB formatting

A 'Begin' is terminated with an 'End'
A ';' separates a statement from the next one
- sounds obvious, but fighting with that made my code less clear

Another thing is to turn on Bounds Checking - and keep it on

Also when dealing with Records that may go down to disk, watch out for
'Packed'

Also declaring proceedures using 'Forward' helps considerably
Given that one declares most of the routines at the top, one might as
well declare the 'private' ones - for completeness.

And, from the mouse right click menu, Complete Class at Cursor, saves
a lot of grunt work

Good Luck with Delphi

0 new messages