Recent

Author Topic: Delimited text - how find last index  (Read 1157 times)

Kropotkin46

  • Newbie
  • Posts: 4
Delimited text - how find last index
« on: April 15, 2026, 02:52:01 am »
Hi,
I'm returning to Lazarus after many years.  Used to drive Pasal, TurboPascal, Delphi and Lazarus but the  skills have faded.

Problem: need to split a string into words  as in eg perl 'split'.

I've failed with SplitString, tried lots od magicspells and none worked.

I stole some online code which showed promise but I can't work out how to terminate the iteration.

The example below at least compiles ok but the 'MyLast' shows as -1, hoping for 3, possibly 4. 
And the ugly repetition of the identifier 'MyList' seems to show that I'm missing a clue!

Help please?  A fix to find the end of the list should be easy but I've spent hours chasing it. 'WordCount' didn't help, either.

A completely different solution would be very welcome.

Using Lazarus (how find verson, no Help|About?) and FPC 3.2.2 on Linux Mint 22.3, 64bit


Code: [Select]

program SplitProg.pas;

uses Classes, StrUtils;
var MyList          : TStringList;
    MyIndex, myLast : Integer;
    MyDelim         : Char = ',';
begin
  MyList := TStringList.Create;
  MyList.Delimiter := ',';
  MyList.StrictDelimiter := True; // Ensures only ',' splits
  MyList.DelimitedText := 'one,two,three,four';

  // MyList[0] = 'one', MyList[1] = 'two', etc.

  WriteLn ( 'MyLast := ', MyList.LastIndexOf(MyList.DelimitedText) );

//for  MyIndex :=  0 to myLast do
// Writeln (MyList[MyIndex]);

  MyList.Free;

end.   


Fibonacci

  • Hero Member
  • *****
  • Posts: 950
  • Behold, I bring salvation - FPC Unleashed
Re: Delimited text - how find last index
« Reply #1 on: April 15, 2026, 03:00:17 am »
Code: Pascal  [Select][+][-]
  1. uses SysUtils;
  2.  
  3. var
  4.   text: string;
  5.   splitted: TStringArray;
  6.   x: integer;
  7.  
  8. begin
  9.   text := 'one,two,three,four';
  10.   writeln('text = ', text);
  11.  
  12.   splitted := text.Split([',']); // array of separators
  13.  
  14.   writeln('items = ', length(splitted));
  15.   x := high(splitted);
  16.   writeln('index of last = ', x);
  17.   writeln('last item = ', splitted[x]);
  18. end.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1593
    • Lebeau Software
Re: Delimited text - how find last index
« Reply #2 on: April 15, 2026, 07:21:54 am »
Problem: need to split a string into words  as in eg perl 'split'.

And, what do you want to do with it after you have split it?

I've failed with SplitString, tried lots od magicspells and none worked.

What exactly did you try that didn't work for you?

I stole some online code which showed promise but I can't work out how to terminate the iteration.

What do you mean by "terminate"? Stop a loop through the list? Use a Break statement.

The example below at least compiles ok but the 'MyLast' shows as -1

Of course it does, because you are searching the split list for the entire original delimited text rather than searching for a specific word in the list.

And the ugly repetition of the identifier 'MyList' seems to show that I'm missing a clue!

You can use a with statement.

Help please?

Help with WHAT, exactly? What is the GOAL you are trying to accomplish?

A fix to find the end of the list should be easy but I've spent hours chasing it. 'WordCount' didn't help, either.

MyList.Count tells you how many strings are in the list.

MyList.Count-1 tells you the index of the last string in the list.

MyList.LastIndexOf() tells you the index of the last matching string in the list.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Zvoni

  • Hero Member
  • *****
  • Posts: 3381
Re: Delimited text - how find last index
« Reply #3 on: April 15, 2026, 08:47:36 am »
Quick 'n dirty
Code: Pascal  [Select][+][-]
  1. program SplitProg;
  2. {$mode ObjFPC}{$H+}
  3. uses Classes;
  4. var MyList          : TStringList;
  5.     MyIndex, myLast : Integer;
  6.     MyDelim         : Char = ',';
  7.     FirstWord, LastWord:String;
  8. begin
  9.   MyList := TStringList.Create;
  10.   MyList.Delimiter := MyDelim;
  11.   MyList.StrictDelimiter := True; // Ensures only ',' splits
  12.   MyList.DelimitedText := 'one,two,three,four';
  13.  
  14.   FirstWord:=MyList[0];
  15.   LastWord:=MyList[MyList.Count-1];
  16.  
  17.   WriteLn('FirstWord='+FirstWord);
  18.   WriteLn('LastWord='+LastWord);
  19.  
  20.   MyList.Free;
  21.   Readln;
  22. end.
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

Kropotkin46

  • Newbie
  • Posts: 4
Re: Delimited text - how find last index
« Reply #4 on: April 15, 2026, 02:27:02 pm »
Problem: need to split a string into words  as in eg perl 'split'.

And, what do you want to do with it after you have split it? 
 
*** Parse through the incoming NEC2 card, details at https://www.nec2.org/part_3/toc.html.

I've failed with SplitString, tried lots od magicspells and none worked.

What exactly did you try that didn't work for you?
*** Lots, can't remember all of them.

I stole some online code which showed promise but I can't work out how to terminate the iteration.

What do you mean by "terminate"? Stop a loop through the list? Use a Break statement.

*** 'for ..to'  needs to know a definite  final value for 'to'.  I thought ' terminate the iteration' was clear.  Apparently not.


The example below at least compiles ok but the 'MyLast' shows as -1

Of course it does, because you are searching the split list for the entire original delimited text rather than searching for a specific word in the list.

*** I am trying to find the index of the last word, I don't know in advance what word to search for.  I could add a delimiter word to the end of the list?

And the ugly repetition of the identifier 'MyList' seems to show that I'm missing a clue!

You can use a with statement.

**** OK!  I'd forgotten that possibility.

Help please?

Help with WHAT, exactly? What is the GOAL you are trying to accomplish?

*** I'm trying to write an optimiser for an antenna design - specifically the 40m and 15m element of my DX Commander Signature 9.  Also keeping in mind the possibility of a more-general optimiser.  And yes, such an optimiser exists but I can't get it to install, never mind it isn't designed for what I want.

A fix to find the end of the list should be easy but I've spent hours chasing it. 'WordCount' didn't help, either.

MyList.Count tells you how many strings are in the list.

MyList.Count-1 tells you the index of the last string in the list.

MyList.LastIndexOf() tells you the index of the last matching string in the list.

Kropotkin46

  • Newbie
  • Posts: 4
Re: Delimited text - how find last index
« Reply #5 on: April 15, 2026, 02:34:14 pm »
Code: Pascal  [Select][+][-]
  1. uses SysUtils;
  2.  
  3. var
  4.   text: string;
  5.   splitted: TStringArray;
  6.   x: integer;
  7.  
  8. begin
  9.   text := 'one,two,three,four';
  10.   writeln('text = ', text);
  11.  
  12.   splitted := text.Split([',']); // array of separators      //foo.pas(12,20) Error: Illegal qualifier  //Fatal: Compilation aborted
  13.  
  14.   writeln('items = ', length(splitted));
  15.   x := high(splitted);
  16.   writeln('index of last = ', x);
  17.   writeln('last item = ', splitted[x]);
  18. end.

Kropotkin46

  • Newbie
  • Posts: 4
Re: Delimited text - how find last index
« Reply #6 on: April 15, 2026, 02:46:04 pm »
Quick 'n dirty
Code: Pascal  [Select][+][-]
  1. program SplitProg;
  2. {$mode ObjFPC}{$H+}
  3. uses Classes;
  4. var MyList          : TStringList;
  5.     MyIndex, myLast : Integer;
  6.     MyDelim         : Char = ',';
  7.     FirstWord, LastWord:String;
  8. begin
  9.   MyList := TStringList.Create;
  10.   MyList.Delimiter := MyDelim;
  11.   MyList.StrictDelimiter := True; // Ensures only ',' splits
  12.   MyList.DelimitedText := 'one,two,three,four';
  13.  
  14.   FirstWord:=MyList[0];
  15.   LastWord:=MyList[MyList.Count-1];
  16.  
  17.   WriteLn('FirstWord='+FirstWord);
  18.   WriteLn('LastWord='+LastWord);
  19.  
  20.   MyList.Free;
  21.   Readln;
  22. end.

Thank you, that worked!

paweld

  • Hero Member
  • *****
  • Posts: 1619
Re: Delimited text - how find last index
« Reply #7 on: April 16, 2026, 08:50:14 am »
But before you retrieve the values, check whether TStringList contains any elements, e.g.
Code: Pascal  [Select][+][-]
  1.   if MyList.Count > 0 then
  2.   begin
  3.     FirstWord := MyList[0];
  4.     LastWord := MyList[MyList.Count - 1];
  5.   end
  6.   else
  7.   begin
  8.     FirstWord := '';
  9.     LastWord := '';
  10.     ShowMessage('List is empty!');
  11.   end;
Best regards / Pozdrawiam
paweld

Zvoni

  • Hero Member
  • *****
  • Posts: 3381
Re: Delimited text - how find last index
« Reply #8 on: April 16, 2026, 10:44:37 am »
But before you retrieve the values, check whether TStringList contains any elements, e.g.
Code: Pascal  [Select][+][-]
  1.   if MyList.Count > 0 then
  2.   begin
  3.     FirstWord := MyList[0];
  4.     LastWord := MyList[MyList.Count - 1];
  5.   end
  6.   else
  7.   begin
  8.     FirstWord := '';
  9.     LastWord := '';
  10.     ShowMessage('List is empty!');
  11.   end;
Nice defensive programming.
But you are not accounting for a failed split (e.g. "wrong" delimiter)

Since he assigned to Stringlist.Text/DelimitedText, there IS at least one entry

So, i'd rather go with
Code: Pascal  [Select][+][-]
  1.   FirstWord := MyList[0];  //This one MUST exist, irrespective if the split was successful or not
  2.   LastWord := '';
  3.   if MyList.Count > 0 then LastWord := MyList[MyList.Count - 1];
« Last Edit: April 16, 2026, 10:46:26 am 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

paweld

  • Hero Member
  • *****
  • Posts: 1619
Re: Delimited text - how find last index
« Reply #9 on: April 16, 2026, 10:59:33 am »
Quote from: Zvoni
Since he assigned to Stringlist.Text/DelimitedText, there IS at least one entry
If you pass an empty string, the list will remain empty and
Code: Pascal  [Select][+][-]
  1. FirstWord := MyList[0];  //This one MUST exist, irrespective if the split was successful or not
will return an AccessViolation
Best regards / Pozdrawiam
paweld

Zvoni

  • Hero Member
  • *****
  • Posts: 3381
Re: Delimited text - how find last index
« Reply #10 on: April 16, 2026, 12:06:34 pm »
Quote from: Zvoni
Since he assigned to Stringlist.Text/DelimitedText, there IS at least one entry
If you pass an empty string, the list will remain empty and
Code: Pascal  [Select][+][-]
  1. FirstWord := MyList[0];  //This one MUST exist, irrespective if the split was successful or not
will return an AccessViolation
Hmm....True enough
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

VisualLab

  • Hero Member
  • *****
  • Posts: 731
Re: Delimited text - how find last index
« Reply #11 on: April 16, 2026, 01:16:56 pm »
The line with the program keyword was missing. Just complete the code:

Code: Pascal  [Select][+][-]
  1. program SplittingText;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. var
  7.   AnyText: string;
  8.   SplittedText: TStringArray;
  9.   AIndex: integer;
  10.  
  11. begin
  12.   AnyText := 'one,two,three,four';
  13.   WriteLn('text = ', AnyText);
  14.   SplittedText := AnyText.Split([',']); // array of separators
  15.   WriteLn('items = ', length(SplittedText));
  16.   AIndex := High(SplittedText);
  17.   WriteLn('index of last = ', AIndex);
  18.   WriteLn('last item = ', SplittedText[AIndex]);
  19.   ReadLn;
  20. end.

Tested in Lazarus 4.6 (Windows 11, 64-bit).

Thaddy

  • Hero Member
  • *****
  • Posts: 19175
  • Glad to be alive.
Re: Delimited text - how find last index
« Reply #12 on: April 16, 2026, 01:38:00 pm »
@VisualLab

The program line is optional and not required in Freepascal.
Freepascal ignores it.
Example:
Code: Pascal  [Select][+][-]
  1. //full program
  2. begin
  3. end.

 O:-)
« Last Edit: April 16, 2026, 01:43:23 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Aruna

  • Hero Member
  • *****
  • Posts: 799
Re: Delimited text - how find last index
« Reply #13 on: April 16, 2026, 04:02:11 pm »
The example below at least compiles ok but the 'MyLast' shows as -1, hoping for 3, possibly 4. 

This has been answered by others am just trying to shed some light on why this happens.
The problem: MyList.LastIndexOf(MyList.DelimitedText)
MyList.DelimitedText = 'one,two,three,four' (the whole string)

But your list contains:
Code: Pascal  [Select][+][-]
  1. "one'
  2. 'two'
  3. 'three'
  4. 'four'
  5.  
So it tries to find 'one,two,three,four' inside the list → not found → returns -1

That’s why you get -1.

The simple fix :
Use .Count instead:
Code: Pascal  [Select][+][-]
  1. myLast := MyList.Count - 1;
  2. WriteLn('MyLast := ', myLast);
  3.  
  4. for MyIndex := 0 to myLast do
  5.   WriteLn(MyList[MyIndex]);

Output:
Code: Pascal  [Select][+][-]
  1. MyLast := 3
  2. one
  3. two
  4. three
  5. four


Using Lazarus (how find verson, no Help|About?) and FPC 3.2.2 on Linux Mint 22.3, 64bit
I have attached a zip file for you to test and play with. Have fun. The attached screenshot shows you this  in action.
« Last Edit: April 16, 2026, 05:59:01 pm by Aruna »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1593
    • Lebeau Software
Re: Delimited text - how find last index
« Reply #14 on: April 17, 2026, 02:26:15 am »
'for ..to'  needs to know a definite  final value for 'to'.  I thought ' terminate the iteration' was clear.  Apparently not.

If you are going to iterate through a TStringList using indexes then you would use the TStringList.Count property as the final value, eg:

Code: Pascal  [Select][+][-]
  1. var i: Integer;
  2. for i := 0 to myList.Count-1 do

Alternatively, you can use a for..in loop instead (if you don't need the indexes for anything else):

Code: Pascal  [Select][+][-]
  1. var s: string;
  2. for s in myList do

I am trying to find the index of the last word, I don't know in advance what word to search for.

Then TStringList.Count-1 is what you are looking for.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

 

TinyPortal © 2005-2018