TStringList, Sorted, CaseSensitive and ASCII order [SOLVED] lazarus / 62-General ---------------------------------------------------------------------- Manlio · 2021-05-27 12:18 If I do this:   SL := TStringList.Create;   SL.Sorted := True;   SL.CaseSensitive := True;   SL.Add('A');   SL.Add('b');   SL.Add('C');   SL.Add('d'); I would expect to get the order: A C b d -- i.e. the ASCII order But instead I get: A b C d -- i.e. case insensitive, even though I specified CaseSensitive as True! Is this intentional? If it's intentional, why does changing CaseSensitive makes no difference? Or am I doing something wrong? I just want plain sorting by ascii code... Thank you!! (And sorry for posting in the wrong place!) ---------------------------------------------------------------------- howardpc · 2021-05-27 13:10 If you were to do Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  SL.Add('A' ); SL.Add('b'); SL.Add('C'); SL.Add('d'); SL.add('a'); SL.add('c'); you would see what difference the CaseSensitive property makes. CaseSensitive <> SortInASCIIOrder ---------------------------------------------------------------------- Zvoni · 2021-05-27 13:20 Errr....? Change it around? First Set CaseInsensitive to True, then the Sorted-Property. IIRC, Setting Sorted to True sets SortStyle to sslAuto, which itself triggers a Sort. A sort happening before setting CaseSensitive EDIT: Forget what i said. Just looked into the source of TStringList. If sorted is set to True (which implies SortStyle = sslAuto) it first tries to Find the item if it already exists (because of duplicates) using DoCompareText. Depending on UseLocale it uses either AnsiCompareStr or CompareStr. So, no idea what really happens ---------------------------------------------------------------------- Zvoni · 2021-05-27 14:08 Quote from: howardpc on May 27, 2021, 03:10:03 pm you would see what difference the CaseSensitive property makes. CaseSensitive <> SortInASCIIOrder Have to disagree. From: https://www.freepascal.org/docs- html/rtl/sysutils/comparestr.html QuoteThe comparison of the two strings is case-sensitive. The function does not take internationalization settings into account, it simply compares ASCII values. ---------------------------------------------------------------------- Avinash · 2021-05-27 15:44 Probably buggy for many years... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE OBJFPC}uses Classes, SysUtils;   function CMP(List: TStringList; Index1: Integer; Index2: Integer): Integer;  begin    Result := CompareStr(List.Strings[Index1], List.Strings[Index2]);  end; var  I: Integer;  SL: TStringList;begin  SL := TStringList.Create;   SL.Add('A');  SL.Add('b');  SL.Add('C');  SL.Add('d');   SL.CustomSort(@CMP);   for I := 0 to SL.Count - 1 do    WriteLn(SL.Strings[I]);   SL.Destroy;end. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses Objects; var  I: Integer;  SC: PStringCollection;begin  New(SC, Init(100, 100));   SC^.Insert(NewStr('A'));  SC^.Insert(NewStr('b'));  SC^.Insert(NewStr('C'));  SC^.Insert(NewStr('d'));   for I := 0 to SC^.Count - 1 do    WriteLn(String(SC^.At(I)^));   Dispose(SC, Done);end. ---------------------------------------------------------------------- lucamar · 2021-05-27 18:38 Quote from: Zvoni on May 27, 2021, 04:08:06 pmHave to disagree. From: https://www.freepascal.org/docs- html/rtl/sysutils/comparestr.htmlQuoteThe comparison of the two strings is case-sensitive. The function does not take internationalization settings into account, it simply compares ASCII values. Unfortunate phrasing ... what it means is that it doesn't take into account accented characters, so it'll not sort e.g. à, á. ä, â, etc. with the "A"s, but since it's case-sensitive it will sort "AbaB" as "AaBb". ---------------------------------------------------------------------- winni · 2021-05-27 20:07 Hi! The TstringList has the public procedure Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure CustomSort(CompareFn: TStringListSortCompare);  The compareFn has  this definition Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;   So you can use from  LazUTF8: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function UTF8CompareStr(const S1, S2: string): PtrInt;  This way you get an UTF8 sort for your TStringList; Winni ---------------------------------------------------------------------- Zvoni · 2021-05-28 05:56 Quote from: lucamar on May 27, 2021, 08:38:33 pmQuote from: Zvoni on May 27, 2021, 04:08:06 pmHave to disagree. From: https://www.freepascal.org/docs- html/rtl/sysutils/comparestr.htmlQuoteThe comparison of the two strings is case-sensitive. The function does not take internationalization settings into account, it simply compares ASCII values. Unfortunate phrasing ... what it means is that it doesn't take into account accented characters, so it'll not sort e.g. à, á. ä, â, etc. with the "A"s, but since it's case-sensitive it will sort "AbaB" as "AaBb". That's not making any sense whatsoever (sorry, luca). So either the docs are wrong or the Function is buggy. CompareByte as an alternative? ---------------------------------------------------------------------- Manlio · 2021-05-28 06:21 Quote from: winni on May 27, 2021, 10:07:21 pm The TStringList has the public procedure [..] CustomSort Yes, we can use CustomSort() on an existing list, but we want to do a different thing: we want to have an ASCII-sorted list to which one can go on adding items, where duplicates are ignored, and where the list remains sorted by the ASCII codes of the string. If there isn't already a property that changes this behaviour, then perhaps I can create a descendent class, overriding some method -- I guess the string comparison method? If we can override that specific method, I suppose, everything else should follow automatically: the object will remain sorted, ignore duplicates, etc. all according to the new sorting method (pure ASCII order in this case) So, those of you who know these classes very well, is there a virtual method that does the comparison between strings that we can override, and then things just work? Thanks! ---------------------------------------------------------------------- Manlio · 2021-05-28 06:55 OK, I think I figured out what is happening, and how to do what I want. Here is what I learned: Let's add the following 8 strings to our (Sorted=True) TStringList: Code: [Select] AA aa Aa aA BB bb Bb bB If CaseSensitive is False, and duplicates are ignored, the list will contain: Code: [Select]AA BB An that's OK, duplicates are ignored. If CaseSensitive is True, the list will instead contain: Code: [Select]aa aA Aa AA bb bB Bb BB (And that's just how the default sorting works: first alphabetical, then lower case first ) But what I wanted was a list sorted by ASCII values, resulting in this: Code: [Select]AA Aa BB Bb aA aa bB bb This is purely by ASCII order, and to achieve this I created a new class that overrides DoCompareText like this: Code: [Select] type   TAsciiStrings = class(TStringList)   public     function DoCompareText(const s1,s2 : string) : PtrInt; override;   end; implementation function TAsciiStrings.DoCompareText(const s1, s2: string): PtrInt; begin   Result := CompareStr(s1, s2); end; CompareStr does a pure ASCII comparison, and the result is what I wanted. Thanks to everyone for the suggestions that helped solve the problem, and thanks to those who moved this post to the correct place after I initially started it in the wrong category!