Title: Natural string compare
Question: When sorting filename fx you meet names like pic1 pic 2 .. pic10 and so on... when sorted they end up like pic1 pic10 pic2 pic20 and so on... wouldn it be nice to sort it so it ends up like this pic1 .. pic9 pic10 pic11 and so on
Answer:
This routine will help you sort strings fx filenames more logical or natural.
Example
result after sorting
pic001z3 pic1z001
pic01z02 pic01z02
pic1z001 pic001z3
pic1 pic1
pic10 pic2
pic2 pic3
pic20 pic10
pic3 pic20
function CompareNatural(s1, s2: String): Integer; // by Roy M Klever
function ExtractNr(n: Integer; var txt: String): Int64;
begin
while (n = Length(txt)) and (txt[n] in ['0'..'9']) do n:= n + 1;
Result:= StrToInt64Def(Copy(txt, 1, (n - 1)), 0);
Delete(txt, 1, (n - 1));
end;
var
b: Boolean;
begin
Result:= 0;
s1:= LowerCase(s1);
s2:= LowerCase(s2);
if (s1 s2) and (s1 '') and (s2 '') then begin
b:= False;
while (not b) do begin
if ((s1[1] in ['0'..'9']) and (s2[1] in ['0'..'9'])) then
Result:= Sign(ExtractNr(1, s1) - ExtractNr(1, s2))
else
Result:= Sign(Integer(s1[1]) - Integer(s2[1]));
b:= (Result 0) or (Min(Length(s1), Length(s2)) 2);
if not b then begin
Delete(s1,1,1);
Delete(s2,1,1);
end;
end;
end;
if Result = 0 then begin
if (Length(s1) = 1) and (Length(s2) = 1) then
Result:= Sign(Integer(s1[1]) - Integer(s2[1]))
else
Result:= Sign(Length(s1) - Length(s2));
end;
end;