Recent

Author Topic: [SOLVED] Stringlist.Find in Delphi & Lazarus behaves differently  (Read 6272 times)

JD

  • Hero Member
  • *****
  • Posts: 1909
While trying to port some Delphi code to Lazarus, I discovered that TStringList Find does not behave the same way in Delphi & Lazarus.

A very simple illustration from http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TStringList_Find.html

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   MyList: TStringList;
  4.   Index: Integer;
  5. begin
  6.   MyList := TStringList.Create;
  7.   try
  8.     MyList.Add('Animals');
  9.     MyList.Add('Flowers');
  10.     MyList.Add('Cars');
  11.     MyList.Sort;   { Find will only work on sorted lists! }
  12.     if MyList.Find('Flowers', Index) then
  13.     begin
  14.       ListBox1.Items.AddStrings(MyList);
  15.       Label1.Caption := 'Flowers has an index value of ' + IntToStr(Index);
  16.     end;
  17.   finally
  18.     MyList.Free;
  19.   end;
  20. end;
  21.  

While the example works in Delphi, it fails in Lazarus and throws an EListError exception saying Cannot use find on an unsorted list.

I need to use Find so that the stringlist can be searched using the binary search method. How do I do this in Lazarus?

Thanks,

JD
« Last Edit: August 18, 2017, 07:45:10 pm by JD »
Linux Mint - Lazarus 4.0/FPC 3.2.2,
Windows - Lazarus 4.0/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12567
  • FPC developer.
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #1 on: August 18, 2017, 06:05:56 pm »
Read the text of the exception AND the embarcadero URL you quote.

FIND ONLY WORKS ON SORTED LISTS, so add

Code: Pascal  [Select][+][-]
  1. mylist.sorted:=true;

before adding elements.

The only difference is that Delphi fails silently, and FPC with an exception. Deliberately.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #2 on: August 18, 2017, 06:07:15 pm »
At first I did not see the problem my self the code worked as expected in 1.4.4 then I tried on 1.6.4 and long story sort here is the difference in the code.
Quote
  if Not Sorted then
    Raise EListError.Create(SErrFindNeedsSortedList);
apparently someone things that we do not know how to handle a binary search properly. any way set the property sorted to true in lazarus or copy the tstringlist code to a custom class to make sure that this kind of thing does not happen in the future. I would say to post a bug report but I do not think it qualifies as a bug.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #3 on: August 18, 2017, 06:08:13 pm »
Read the text of the exception AND the embarcadero URL you quote.

FIND ONLY WORKS ON SORTED LISTS, so add

Code: Pascal  [Select][+][-]
  1. mylist.sorted:=true;

before adding elements.

The only difference is that Delphi fails silently, and FPC with an exception. Deliberately.
No, the difference is that delphi does not fail and finds the item required and fpc fails with an exception.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12567
  • FPC developer.
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #4 on: August 18, 2017, 06:55:53 pm »
No, the difference is that delphi does not fail and finds the item required and fpc fails with an exception.

Newer versions might contain fallback to indexof, iirc the older ones didn't. But then it isn't binary search, and it isn't documented

BeniBela

  • Hero Member
  • *****
  • Posts: 948
    • homepage
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #5 on: August 18, 2017, 07:24:18 pm »
I need to use Find so that the stringlist can be searched using the binary search method. How do I do this in Lazarus?

whatever you do, do not add a widestring manager

JD

  • Hero Member
  • *****
  • Posts: 1909
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #6 on: August 18, 2017, 07:44:38 pm »
I need to use Find so that the stringlist can be searched using the binary search method. How do I do this in Lazarus?

whatever you do, do not add a widestring manager

Thanks for the tip. The example now works in Lazarus. And I have no need for a widestring manager in this project.

JD
Linux Mint - Lazarus 4.0/FPC 3.2.2,
Windows - Lazarus 4.0/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

JD

  • Hero Member
  • *****
  • Posts: 1909
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #7 on: August 18, 2017, 07:48:52 pm »
Read the text of the exception AND the embarcadero URL you quote.

FIND ONLY WORKS ON SORTED LISTS, so add

Code: Pascal  [Select][+][-]
  1. mylist.sorted:=true;

before adding elements.

The only difference is that Delphi fails silently, and FPC with an exception. Deliberately.

Thanks marcov. It appears the use of the Sort method is redundant in Lazarus. Anyway it now works.

JD
« Last Edit: August 18, 2017, 07:51:12 pm by JD »
Linux Mint - Lazarus 4.0/FPC 3.2.2,
Windows - Lazarus 4.0/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #8 on: August 18, 2017, 07:54:43 pm »
No, the difference is that delphi does not fail and finds the item required and fpc fails with an exception.

Newer versions might contain fallback to indexof, iirc the older ones didn't. But then it isn't binary search, and it isn't documented
handle it the same way that duplicates are handled, let the end user define the behavior exception, indexof, or silent fail, you can always make the exception the default behavior.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 18524
  • Here stood a man who saw the Elbe and jumped it.
Re: [SOLVED] Stringlist.Find in Delphi & Lazarus behaves differently
« Reply #9 on: August 18, 2017, 09:17:45 pm »
Use IndexOf instead of find. If sorted = false it will fall back to linear search else binary search.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

 

TinyPortal © 2005-2018