Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the sort order in Delphi as in Windows Explorer?

Summarization:

  1. The terminology that I have been looking for seems to be "natural sort".
  2. For behaviors in operating systems:

    • For Windows (version >= XP), Windows Explorer utilizes natural sort.
    • For Linux terminals: use "ls -v" instead of plain "ls" to get natural sort.
  3. For programing in Delphi, use StrCmpLogicalW Windows API to get natural sort.

  4. For programing in Delphi & Kylix & Lazarus, use hand-crafted functions to get natural sort:
    • (1) Delphi wrapper for Natural Order String Comparison by Martin Pool.
      http://irsoft.de/web/strnatcmp-and-natsort-for-delphi
    • (2) Codes of alphanum sorting algorithm in other languages from davekeolle site.
      http://www.davekoelle.com/alphanum.html
    • (3) Other knowledgable pages:
      http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html
      http://objectmix.com/delphi/722211-natural-sorting-optimizing-working-solution.html
      http://groups.google.com/group/borland.public.delphi.language.delphi.general/browse_thread/thread/1141d49f8bbba577
      http://objectmix.com/delphi/401713-alphanumeric-sort-routine-delphi.html

==========================

The following file names will be ordered in the Windows Explorer as shown below:

test_1_test.txt

test_2_test.txt

test_11_test.txt

test_12_test.txt

test_21_test.txt

test_22_test.txt

If, for example, I put them in a TStringList instance and call Sort, the sorted order is as below:

test_1_test.txt

test_11_test.txt

test_12_test.txt

test_2_test.txt

test_21_test.txt

test_22_test.txt

And for record, the above file names will be ordered in the rxvt terminal of Cygwin or xterm terminal of Linux distributions such as CentOS as shown below:

test_11_test.txt

test_12_test.txt

test_1_test.txt

test_21_test.txt

test_22_test.txt

test_2_test.txt

Could you help to comment on how to understand this difference of sorting behaviors? Furthermore, is it possible to get the same order as in Windows Explorer? Any suggestion is appreciated!

PS: My Windows locale is set to Chinese but I would think the same for English locale.

like image 559
SOUser Avatar asked Feb 27 '11 17:02

SOUser


People also ask

How does Windows Explorer sort file names?

Since then, Microsoft has used a sorting algorithm in which file and folder names are sorted numerically in Windows/File Explorer. As you can see in Figure A, in the literal sorting system, files whose names include numbers are arranged by each digit in the filename. Since 1 comes before 2, 111 comes before 22.


2 Answers

StrCmpLogicalW is able to handle numbers, the other alternative is CompareString

like image 54
Anders Avatar answered Oct 13 '22 00:10

Anders


Thanks to Anders - the answer is StrCmpLogicalW; I have not found it's declaration in Delphi 2009 sources, so I declared it myself in the test below:

type
  TMyStringList = class(TStringList)
  protected
    function CompareStrings(const S1, S2: string): Integer; override;
  end;

function StrCmpLogicalW(P1, P2: PWideChar): Integer;  stdcall; external 'Shlwapi.dll';

function TMyStringList.CompareStrings(const S1, S2: string): Integer;
begin
  Result:= StrCmpLogicalW(PChar(S1), PChar(S2));
end;

procedure TForm11.Button2Click(Sender: TObject);
var
  SL: TMyStringList;

begin
  SL:= TMyStringList.Create;
  try
    SL.Add('test_1_test.txt');
    SL.Add('test_11_test.txt');
    SL.Add('test_12_test.txt');
    SL.Add('test_2_test.txt');
    SL.Add('test_21_test.txt');
    SL.Add('test_22_test.txt');
    SL.Sort;
    Memo1.Lines:= SL;
  finally
    SL.Free;
  end;
end;
like image 20
kludg Avatar answered Oct 13 '22 00:10

kludg