Board index » delphi » String lists not sorting properly, example code to try

String lists not sorting properly, example code to try

Further to my post a few days ago I have produced a small test app which
demonstrates the problem.  It consists of a form with two list boxes and two
buttons, ListBox2 is sorted, ListBox1 is not.  The example has the word
length set to 1 at the moment,which demonstrates the problem the best.  It
fills the first list with random strings and then copies them all over to the
second list box.  They should all be sorted into alphabetical order, however,
you will notice that the upper and lower case letters are sorted
randomly....WHY?  I know the sorting algorithm uses the AnsiStrComp function
and so upper and lower case letters appear together, but single character
strings should group all the same lower and upper case letters together ie.
should go a,a,a,a,A,A,A not a,a,A,a,A,A,a...............!

unit SortTest;

interface

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

type
  TSortingChecker = class(TForm)
    ListBox1: TListBox;
    ListBox2: TListBox;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

var
  SortingChecker: TSortingChecker;

implementation

{$R *.DFM}

procedure TSortingChecker.Button1Click(Sender: TObject);
var
  i: Integer;
  j: Integer;
  CharSpan: integer;
  str: String;

const
  NUMBER_WORDS = 500;
  LONGEST_WORD = 1;

begin
  //Fill first list box with random strings
  Randomize;
  ListBox1.Clear;
  CharSpan := Ord('z') - 32;
  for i := 0 to NUMBER_WORDS do
  begin
    str := '';
    for j := 0 to Random(LONGEST_WORD) do
      str := str + chr(Random(CharSpan)+ 32) ;
    if str <> '' then
      Listbox1.Items.Add(str);
  end;
end;

procedure TSortingChecker.Button2Click(Sender: TObject);
var
  i: Integer;

begin
  Listbox2.clear;
  //ListBox2 is sorted, copy the strings across to it
  for i := 0 to Listbox1.Items.Count - 1 do
    Listbox2.Items.Add(Listbox1.Items[i]);
  //Some of the strings will not be in order!
end;

end.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    

 

Re:String lists not sorting properly, example code to try


Quote
On Wed, 13 Jan 1999 21:44:43 GMT, t.h...@trl.telstra.com.au wrote:
>Further to my post a few days ago I have produced a small test app which
>demonstrates the problem.  It consists of a form with two list boxes and two
>buttons, ListBox2 is sorted, ListBox1 is not.  The example has the word
>length set to 1 at the moment,which demonstrates the problem the best.      It
>fills the first list with random strings and then copies them all over to the
>second list box.  They should all be sorted into alphabetical order, however,
>you will notice that the upper and lower case letters are sorted
>randomly....WHY?  I know the sorting algorithm uses the AnsiStrComp function
>and so upper and lower case letters appear together, but single character
>strings should group all the same lower and upper case letters together ie.
>should go a,a,a,a,A,A,A not a,a,A,a,A,A,a...............!

Well, they _are_ sorted in ALPHABETICAL order. Upper/lower case has
(normally) nothing to do with the alphabet.

This is the way both listboxes and stringlists _are_ sorted (Could
there be a difference depending on locale? I don't know). You have to
write a sorting routine of Your own (and use an unsorted listbox) to
get what You want. Check the WINAPI help for CompareString or lstrcmp.

AnsiStrComp - what's this? Not found in D2.

------------------------------------
Anders Isaksson, Sweden

BlockCAD: http://user.tninet.se/~hbh828t/proglego.htm
Gallery:  http://user.tninet.se/~hbh828t/gallery.htm

Re:String lists not sorting properly, example code to try


Quote
In article <77j448$fj...@nnrp1.dejanews.com>, t.h...@trl.telstra.com.au writes:
>Further to my post a few days ago I have produced a small test app which
>demonstrates the problem.  It consists of a form with two list boxes and two
>buttons, ListBox2 is sorted, ListBox1 is not.  The example has the word
>length set to 1 at the moment,which demonstrates the problem the best.
It
>fills the first list with random strings and then copies them all over to the
>second list box.  They should all be sorted into alphabetical order, however,
>you will notice that the upper and lower case letters are sorted
>randomly....WHY?  I know the sorting algorithm uses the AnsiStrComp function
>and so upper and lower case letters appear together, but single character
>strings should group all the same lower and upper case letters together ie.
>should go a,a,a,a,A,A,A not a,a,A,a,A,A,a...............!

I think that there are two aspects to the sorting :-
1 The case of the characters
2 The length of the strings

AnsiCompareText (which I believe the TListBox sort uses) ignores the case of
the characters and would give you the random case effect you see. The lnegth of
string menas that "A<sp><sp><sp>". is greater that "A". Combine the two and you
get some odd effects.

Perhaps the only way is to "roll your own" as follows :-

function SortMe(S1, S2 : string; Len : integer) : integer;
{returns <0 if S1 less than S2, 0 if equal, >0 if S1 > S2}
{fills both strings to same length with spaces before comparing}
var
  SLen1, SLen2 : shortstring;

  procedure SetSLen(var SLen :shortstring; S : string; L : integer);
  var
    i : integer;
  begin
    for i := 1 to Length(S) do SLen[i] := S[i];
    for i := Length(S) + 1 to L do SLen[i] := ' ';
    SetLength(SLen, L);
  end;

begin
  SetSLen(SLen1, S1, Len);
  SetSLen(SLen2, S2, Len);
  Result := AnsiCompareStr(SLen1, SLen2);
end;

procedure SortListBox(LB : TListBox);
var
  i, SortLen : integer;
  Sorted : boolean;

  function Max(X, Y: Integer): Integer;
  begin
    Result := X;
    if Y > X then Result := Y;
  end;

begin
  {this does the sorting}
  SortLen := 0;  // eventually is max length of all strins in listbox
  LB.Items.BeginUpdate;
  repeat
    Sorted := true;
    with LB.Items do
      for i := 0 to Count - 2 do  begin
        SortLen := Max(SortLen, Max(Length(Strings[i]), Length(Strings[i+1])));
        if SortMe(Strings[i], Strings [i+1], SortLen) > 0 then begin
          Exchange(i, i+1);
          Sorted := false;
        end;
      end;
  until Sorted;
  LB.Items.EndUpdate;
end;

Alan Lloyd
alangll...@aol.com

Re:String lists not sorting properly, example code to try


In article <77j448$fj...@nnrp1.dejanews.com>,

Quote
  t.h...@trl.telstra.com.au wrote:
> Further to my post a few days ago I have produced a small test app which
> demonstrates the problem.  It consists of a form with two list boxes and two
> buttons, ListBox2 is sorted, ListBox1 is not.  The example has the word
> length set to 1 at the moment,which demonstrates the problem the best.

      You need to describe the problem more carefully - we all assumed from
the title that you were talking about TStringlist's, but there are no
stringlists at all in your example.

      (Evidently) the sort used by listboxes is case-insensitive.
Who said it was supposed to be case-sensitive?

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    

Other Threads