# Alphanumeric sort routine in delphi - Delphi

This is a discussion on Alphanumeric sort routine in delphi - Delphi ; 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 ...

1. ## Alphanumeric sort routine in delphi

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

2. ## Re: Alphanumeric sort routine in delphi

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

3. ## Re: Alphanumeric sort routine in delphi

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)

4. ## Re: Alphanumeric sort routine in delphi

"Veronica Mae" <veronica@sexgooroo.com> wrote in
news:476e7e1f@newsgroups.borland.com:
> I need a good alphanumerical sorting routine written in delphi.

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

5. ## Re: Alphanumeric sort routine in delphi

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;