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

Alphanumeric sort routine in delphi

546 views
Skip to first unread message

Veronica Mae

unread,
Dec 23, 2007, 10:25:55 AM12/23/07
to
Hi everyone!

I need a good alphanumerical sorting routine written in delphi.

Normally, WideCompareStr will arrange strings like this:

text1
text12
text123
text2
text3

Instead of that, I need to arrange my strings this way:

text1
text2
text3
text12
text123

I've been searching the net hours for a routine like this, but didn't find
any.

Any help would be greatly appreciated!

Note: It should just be a basic comparision routine that I can use to
arrange TListView columns!

Thanks!

Veronica

Roy Lambert

unread,
Dec 23, 2007, 10:53:49 AM12/23/07
to
Veronica


I'm not surprised that you can't find anything. You have a compound key the first part is text and the second part is a number. The easiest way to handle it is to left pad the numbers either with a space or 0 which makes sorting easy ..

text001
text002
text003
text012
text123

otherwise you have to split the string into its component string and number, do a first sort on the text and then sort within that for the number and I have no idea how to do that.

Roy Lambert

Woody (TMW)

unread,
Dec 23, 2007, 11:26:45 AM12/23/07
to
Veronica Mae wrote:
> Hi everyone!
>
> I need a good alphanumerical sorting routine written in delphi.
>

Most list components have the ability to call a method
when they compare two items for sorting. You can use that
method to compare the two parts of each string.

First you need a function to strip off the numeric part
and return the string:
(This is assuming that there will be no numbers within
the actual string portion of the data.)

function StripNumbers(Value: string): string;
var
x: integer;

begin
x := 1;
while (x < length(Value) and not (Value[x] in ['0'..'9']) do
inc(x);
result := copy(Value, 1, x - 1);
end;


Then you need a function for stripping off the number:
(The function below ignores leading characters until
it reaches any numeric(integer) sign, including minus, plus and
commas. I have another which does the same for floating
point numbers. I use both regularly for things like this.)

function GetNumber(Value: string): integer;
var
x: integer;
s1: string;
Neg: boolean;

begin
Value := Trim(Value);
if Value = '' then
Result := 0
else
try
Neg := False;
s1 := '0';
for x := 1 to length(s) do
if Value[x] in ['-', '+', '0'..'9', ','] then begin
if not (Value[x] in ['-', ',']) then
s1 := s1 + Value[x]
else if (Value[x] = '-') and (x = 1) then
Neg := True;
end else if s1 <> '0' then
break;
Result := StrToInt(s1);
if Neg then
Result := Result * -1;
except
Result := 0;
end;
end;


Now, you can just compare the two parts in your sorting
routine. If the string portions are equal, then test the
numeric portion.

HTH
Woody (TMW)

Iman L Crawford

unread,
Dec 23, 2007, 2:46:22 PM12/23/07
to
"Veronica Mae" <vero...@sexgooroo.com> wrote in
news:476e...@newsgroups.borland.com:

> I need a good alphanumerical sorting routine written in delphi.

http://www.google.com/search?hl=en&q=delphi+natural+sort+order&btnG=Search

brings back quite a few hits. The first a link to some code and the second
a pretty good discussion with links to some paper on natural sort.

--

Iman

Chris

unread,
Dec 24, 2007, 8:44:25 AM12/24/07
to
Veronica Mae wrote:
> Hi everyone!
>
> I need a good alphanumerical sorting routine written in delphi.
>
> Normally, WideCompareStr will arrange strings like this:
>
> text1
> text12
> text123
> text2
> text3
>
> Instead of that, I need to arrange my strings this way:
>
> text1
> text2
> text3
> text12
> text123
>
> Veronica
>
>
>

StrCmpLogicalW() does what you want.

....

function StrCmpLogicalW(psz1, psz2: PWideChar): Integer; Stdcall;
procedure SortLogicalW(Strs: TStrings);

implementation

function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

procedure SortLogicalW(Strs: TStrings);

function _SortW(List: TStrings; Index1, Index2: Integer): Integer;
begin
result := StrCmpLogicalW( PWideChar(WideString(List[Index1])),
PWideChar(WideString(List[Index2])) );
end;

var
buffer : TStringList;
begin
if Strs.Count > 1 then begin
buffer := TStringList.Create;
try
buffer.Assign(Strs);

buffer.CustomSort(@_SortW);

Strs.Assign(buffer);
finally
buffer.Free;
end;
end;
end;

0 new messages