Recent

Author Topic: Comparing a string to the next in a list  (Read 3544 times)

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Comparing a string to the next in a list
« on: September 16, 2021, 03:06:01 pm »
Dear ALL,

I want to compare each string in a list with the next string in the same list, printing it if they are identical.

I tried two versions, as shown below:

version 1

Code: Pascal  [Select][+][-]
  1. program comp1;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses Classes;
  6.  
  7. var
  8.   s: TStringList;
  9.   i: integer;
  10.  
  11. begin
  12.   s := TStringList.Create;
  13.   s.Add('this');
  14.   s.Add('this');
  15.   s.Add('and');
  16.   s.Add('that');
  17.   for i := 1 to s.Count do
  18.   begin
  19.     if s[i] = s[i - 1] then
  20.           WriteLn(s[i]);
  21.   end;
  22.   s.Free;
  23. end.
  24.  

version 2:

Code: Pascal  [Select][+][-]
  1. program comp2;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses Classes;
  6.  
  7. var
  8.   s: TStringList;
  9.   i: integer;
  10.  
  11. begin
  12.   s := TStringList.Create;
  13.   s.Add('this');
  14.   s.Add('this');
  15.   s.Add('and');
  16.   s.Add('that');
  17.   for i := 0 to s.Count - 1 do
  18.   begin
  19.     if s[i] = s[i + 1] then
  20.           WriteLn(s[i]);
  21.   end;
  22.   s.Free;
  23. end.
  24.  
Both versions give me out-of-bounds errors!  %)

Could someone point out what is wrong? I feel rather dumb today.

Thanks in advance!
« Last Edit: September 17, 2021, 02:34:31 pm by maurobio »
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Comparing a string to the next in a list
« Reply #1 on: September 16, 2021, 03:45:04 pm »
Version 1:
You run i from 1 to s.count which is 4 in your sample. You compare s[ i] with s[i-1] --> There is no Member with Index 4

The same in Version 2:
you run i from 0 to s.count-1 which equals 3. You compare s[ i] with s[i+1] --> There is no Member with Index 4
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11351
  • FPC developer.
Re: Comparing a string to the next in a list
« Reply #2 on: September 16, 2021, 03:46:04 pm »
first can do a s[ i] with i=s.count, which is out of bounds.

second can do s[i+1] with i=s.count-1 which is effectively also  s[ i] with i=s.count, which is out of bounds.

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Comparing a string to the next in a list
« Reply #3 on: September 16, 2021, 03:48:40 pm »
No Out-Of-Bounds-Error:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. Uses
  4.   Classes;
  5.  
  6. Var
  7.   s:TStringList;
  8.   i:Integer;
  9.  
  10. begin
  11.   s:=TStringList.Create;
  12.   s.Add('this');
  13.   s.add('this');
  14.   s.add('and');
  15.   s.add('that');
  16.   For i:=s.count-1 DownTo 1 Do
  17.       If s[i]=s[i-1] Then WriteLn(s[i]);
  18. //The other direction
  19.   For i:=0 To s.count-2 Do
  20.       If s[i]=s[i+1] Then WriteLn(s[i]);
  21.   s.Free;
  22. end.
  23.  

EDIT: What's the purpose of this comparison?
« Last Edit: September 16, 2021, 03:53:02 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Comparing a string to the next in a list
« Reply #4 on: September 16, 2021, 09:37:37 pm »
@Zvoni,

Thanks a lot for your suggestions, they were quite helpful.

That sample code had no other purpose than illustrate my problem. But what I really want is to perform a statistical comparison of each string in a list with all others in the same list, using one of the indexes provided in the FuzzyWuzzy library (https://github.com/DavidMoraisFerreira/FuzzyWuzzy.pas).

Here is another sample, in which the list contains botanical names:

Code: Pascal  [Select][+][-]
  1. program comp;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses Classes, FuzzyWuzzy;
  6.  
  7. var
  8.   s: TStringList;
  9.   i: integer;
  10.  
  11. begin
  12.   s := TStringList.Create;
  13.   s.Add('Anacardium occidentale');
  14.   s.Add('Unknown 1');
  15.   s.Add('Unknown 2');
  16.   s.Add('Eriotheca sp.');
  17.   s.Add('Dead dead');
  18.   s.Add('Myrcia lengua');
  19.   s.Add('Myrcia lingua');
  20.   s.Add('Myrcia sp1');
  21.   s.Add('Myrcia sp2');
  22.   s.Add('Myrcia sp3');
  23.   s.Add('Pseudobombax sp.');
  24.   s.Add('Trema micranthum');
  25.  
  26.   for i := 0 to s.Count - 2 do
  27.   begin
  28.     if PartialRatio(s[i], s[i + 1]) > 90 then
  29.           WriteLn(s[i]);
  30.   end;
  31.   s.Free;
  32. end.
  33.  

It works, incorporating one of your suggestions.

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Comparing a string to the next in a list
« Reply #5 on: September 17, 2021, 11:57:14 am »
That sample code had no other purpose than illustrate my problem. But what I really want is to perform a statistical comparison of each string in a list with all others in the same list, using one of the indexes provided in the FuzzyWuzzy library (https://github.com/DavidMoraisFerreira/FuzzyWuzzy.pas).
Uh, you do realize, that's not what you're doing with your simple loop?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: [SOLVED] Comparing a string to the next in a list
« Reply #6 on: September 17, 2021, 01:29:50 pm »
@Zvoni,

Of course, as I wrote in my previous message, it is working fine.

Thank you!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: [SOLVED] Comparing a string to the next in a list
« Reply #7 on: September 17, 2021, 01:31:02 pm »
You sure?
In your sample above, you never compare "Myrcia lengua" with "Myrcia sp3"
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: [SOLVED] Comparing a string to the next in a list
« Reply #8 on: September 17, 2021, 01:34:05 pm »
@Zvoni,

Why not? As far as I can see, the algorithm seems to be working fine - "Myrcia lengua" is correctly identified as an ortographic error.

Regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: [SOLVED] Comparing a string to the next in a list
« Reply #9 on: September 17, 2021, 01:50:52 pm »
You misunderstood:
You compare "Myrcia lengua" with "Dead dead" and "Myrcia lingua" but never with "Myrcia sp1"
It's contrary to what you wrote: to compare EACH string with EVERY other string of the List.
Nevermind sorted vs. unsorted List
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: [SOLVED] Comparing a string to the next in a list
« Reply #10 on: September 17, 2021, 01:55:09 pm »
@Zvoni,

Perhaps you could provide an example of how the algorithm should better work?

The lists which I use are always sorted by species name.

Regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: [SOLVED] Comparing a string to the next in a list
« Reply #11 on: September 17, 2021, 02:16:23 pm »
After thinking about it: The question is not sorted vs. unsorted List, but "Do you really need to compare EACH string with EVERY other String of the List"?
Basically it boils down to running through your List and compare each entry with every other entry.

Of the top of my head, i'd probably go along these lines:
2 Loops.
2 StringLists (initially identical)
Outer Loop: Take (current) entry of List1 and remove this entry from List2 (to avoid comparing it with itself)
Inner Loop: Run through List2 and do your comparisons. --> If you need to save the result you have to provide a place to store it (The associated Object of the StringList-Entry?) or you process the Result directly.

The result of the above is, that List2 shrinks consecutively, since you're removing the current entry from List2, and there is no difference in result for, e.g.
PartialRatio('Myrcia lengua','Myrcia sp3') and PartialRatio('Myrcia sp3,'Myrcia lengua') (commutative).

As i said: From the top of my head. Pretty sure someone else might chip in with something better.

btw: In my above example both Lists have to be in the same order (that's where sorted gives an advantage) and I'd run through both Lists Top-Down, since you'd always remove the last entry (no overhead moving memory around) in List2

EDIT: Maybe remove the "[SOLVED]" from the Subject?
« Last Edit: September 17, 2021, 02:18:02 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: Comparing a string to the next in a list
« Reply #12 on: September 17, 2021, 02:36:48 pm »
@Zvoni,

Not sure if I understood correctly, anyway I removed the [SOLVED] tag from the message subject per your suggestion.

I will have to try the algorithm with a larger sample of names.

Regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1088
  • Professional amateur ;-P
Re: Comparing a string to the next in a list
« Reply #13 on: September 17, 2021, 02:42:19 pm »
Boas Maurobio,

Attached is a sample project that will compare all the strings to each other, skipping the ones with the same index.

I made it visually appealing with two List Boxes that animate where the comparison is made.

Points of interest on the code:
Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.FormCreate(Sender: TObject);
  2. begin
  3.   FWordList:= TStringList.Create;
  4.   FWordList.Add('Anacardium occidentale');
  5.   FWordList.Add('Unknown 1');
  6.   FWordList.Add('Unknown 2');
  7.   FWordList.Add('Eriotheca sp.');
  8.   FWordList.Add('Dead dead');
  9.   FWordList.Add('Myrcia lengua');
  10.   FWordList.Add('Myrcia lingua');
  11.   FWordList.Add('Myrcia sp1');
  12.   FWordList.Add('Myrcia sp2');
  13.   FWordList.Add('Myrcia sp3');
  14.   FWordList.Add('Pseudobombax sp.');
  15.   FWordList.Add('Trema micranthum');
  16.  
  17.   lbLeft.Items.Text:= FWordList.Text;
  18.   lbRight.Items.Text:= FWordList.Text;
  19. end;
  20.  
  21. procedure TfrmMain.actCompareGoExecute(Sender: TObject);
  22. var
  23.   indexLeft, indexRight: Integer;
  24. begin
  25.   actCompareGo.Enabled:= False;
  26.   Application.ProcessMessages;
  27.   try
  28.     for indexLeft:= 0 to Pred(FWordList.Count) do
  29.     begin
  30.       for indexRight:= 0 to Pred(FwordList.Count) do
  31.       begin
  32.         if indexLeft = indexRight then continue;
  33.         lbLeft.ItemIndex:= indexLeft;
  34.         lbRight.ItemIndex:= indexRight;
  35.         {
  36.           This is where you should perform your FuzzyWuzzy compare.
  37.           I'm just doing an equals.
  38.         }
  39.         if FWordList[indexLeft] = FWordList[indexRight] then
  40.         begin
  41.           memLog.Append(Format(
  42.             'String index %d is identical to String index %d ("%s" = "%s")',
  43.             [
  44.               indexLeft,
  45.               indexRight,
  46.               FWordList[indexLeft],
  47.               FWordList[indexRight]
  48.             ]
  49.           ));
  50.         end;
  51.         Application.ProcessMessages;
  52.         Sleep(80);
  53.       end;
  54.     end;
  55.   finally
  56.     lbLeft.ItemIndex:= -1;
  57.     lbRight.ItemIndex:= -1;
  58.     Application.ProcessMessages;
  59.     actCompareGo.Enabled:= True;
  60.   end;
  61. end;
  62.  

Hope this helps clarify the compare every string in a list with all the strings in the list challenge you were trying.

Grande abraço,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Comparing a string to the next in a list
« Reply #14 on: September 17, 2021, 02:52:57 pm »
Gus,
you do realize (i admit, haven't looked too closely) that you compare strings twice?
e.g.
in your left List (outer loop) you reach Member 4 and compare it with each Member of the right List (inner Loop) except Member 4, for example member 7
Now, you reach in your left List Member 7 and compare it with each Member of the right list except Member 7, but you compare it (again) with Member 4!

It's why i assumed, FuzzyWuzzy returns the same result for (Member4,Member7) and (Member7,Member4) --> commutative
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018