Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-07

splitting string into array

18 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marc Santhoff

Hi,

is there any function in the libraries of fpc for splitting a string into an array naming the separator?

In awk for eample if you do this:

split("ab-cd-ef", x, "-")
print x[2]

it would split up the first string using "-" as separator and print

cd

to the output. That's what I'm searching for.
In pascal. ;)

TIA,
Marc

Reply by email

Daniël Mantione
to Marc Santhoff: is there any function in the libraries of fpc for splitting a string into an array naming…

Op Tue, 10 Jul 2007, schreef Marc Santhoff:

Show quoted text 16 lines
Hi, is there any function in the libraries of fpc for splitting a string into an array naming the separator? In awk for eample if you do this: split("ab-cd-ef", x, "-") print x[2] it would split up the first string using "-" as separator and print cd to the output. That's what I'm searching for. In pascal. ;)

In dynamically typed languages writing such a construction is very easy because one can simply allocate an array at runtime of the needed type (if there are multiple types at all).

In Pascal, being a statically typed language, the array element does matter and cannot be decided an array at
runtime is possible to, but inefficient because the size isn't known in advance, growing it one element at a time is a good way to fragment the heap.

Daniël

Reply by email

Marc Santhoff
to Luca Olivetti: En/na Marc Santhoff ha escrit: not exactly but I found:…
Luca Olivetti wrote 12 lines
En/na Marc Santhoff ha escrit: > Hi, > > is there any function in the libraries of fpc for splitting a string > into an array naming the separator? not exactly but I found: http://www.freepascal.org/docs-html/rtl/strutils/extractdelimited.html maybe exactly what you're searching is already there, somewhere....

Okay, I found that one already and it does the basic part of what I need.

I only wanted to make sure I did not overlook something, I had the strong feeling the needed function would exist (must have been another language).

@Daniël:
There is no problem using dynamic arrays here, because the data to read in is textual arrays with relatively small dimension sizes, from 5x5 to 25x25 and anything in between.

But you're right, the problem might be redimensioning the dynamic array to the final size ... will see. ;)

Thank you both,
Marc

Reply by email

Wolfram Kläger

Here is a Delphi implementation of the common PHP function 'explode'.

http://www.michael-puff.de/Developer/Delphi/Code-Snippets/Explode.html

Your example then becomes to
..
A := Explode('-', 'ab-cd-ef');
writeln(A[1]); // expect 'cd'
..

The inverse is accomplished by using PHP like 'implode', which glues all splitted parts back to a single string.

Wolfram

Show quoted text 5 lines
-----Ursprüngliche Nachricht----- Von: FPC-Pascal users discussions Gesendet: 10.07.07 13:04:31 An: FPC-Pascal users discussions Betreff: [fpc-pascal] splitting string into array
Show quoted text 26 lines
Hi, is there any function in the libraries of fpc for splitting a string into an array naming the separator? In awk for eample if you do this: split("ab-cd-ef", x, "-") print x[2] it would split up the first string using "-" as separator and print cd to the output. That's what I'm searching for. In pascal. ;) TIA, Marc _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Andrea Mauri
to Wolfram Kläger

I used this, check it.

// Returns an array with the parts of "str" separated by "separator"
function Split(const str: string; const separator: string): array of string;
var
  i, n: integer;
  strline, strfield: string;
begin
  n:= Occurs(str, separator);
  SetLength(Result, n + 1);
  i := 0;
  strline:= str;
  repeat
    if Pos(separator, strline) > 0 then
    begin
      strfield:= Copy(strline, 1, Pos(separator, strline) - 1);
      strline:= Copy(strline, Pos(separator, strline) + 1,
Length(strline) - pos(separator,strline));
    end
    else
    begin
      strfield:= strline;
      strline:= '';
    end;
    Result[i]:= strfield;
    Inc(i);
  until strline= '';
  if Result[High(Result)] = '' then SetLength(Result, Length(Result) -1);
end;

andrea

Wolfram Kläger ha scritto:

Show quoted text 57 lines
Here is a Delphi implementation of the common PHP function 'explode'. http://www.michael-puff.de/Developer/Delphi/Code-Snippets/Explode.html Your example then becomes to .. A := Explode('-', 'ab-cd-ef'); writeln(A[1]); // expect 'cd' .. The inverse is accomplished by using PHP like 'implode', which glues all splitted parts back to a single string. Wolfram > -----Ursprüngliche Nachricht----- > Von: FPC-Pascal users discussions > Gesendet: 10.07.07 13:04:31 > An: FPC-Pascal users discussions > Betreff: [fpc-pascal] splitting string into array > > Hi, > > is there any function in the libraries of fpc for splitting a string > into an array naming the separator? > > In awk for eample if you do this: > > split("ab-cd-ef", x, "-") > print x[2] > > it would split up the first string using "-" as separator and print > > cd > > to the output. That's what I'm searching for. > In pascal. ;) > > TIA, > Marc > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Andrea Mauri
to Andrea Mauri

occurs is:

function Occurs(const str, separator: string): integer;
var
  i, nSep: integer;
begin
  nSep:= 0;
  for i:= 1 to Length(str) do
    if str[i] = separator then Inc(nSep);
  Result:= nSep;
end;

Andrea Mauri ha scritto:

Show quoted text 96 lines
I used this, check it. // Returns an array with the parts of "str" separated by "separator" function Split(const str: string; const separator: string): array of string; var i, n: integer; strline, strfield: string; begin n:= Occurs(str, separator); SetLength(Result, n + 1); i := 0; strline:= str; repeat if Pos(separator, strline) > 0 then begin strfield:= Copy(strline, 1, Pos(separator, strline) - 1); strline:= Copy(strline, Pos(separator, strline) + 1, Length(strline) - pos(separator,strline)); end else begin strfield:= strline; strline:= ''; end; Result[i]:= strfield; Inc(i); until strline= ''; if Result[High(Result)] = '' then SetLength(Result, Length(Result) -1); end; andrea Wolfram Kläger ha scritto: > Here is a Delphi implementation of the common PHP function 'explode'. > > http://www.michael-puff.de/Developer/Delphi/Code-Snippets/Explode.html > > Your example then becomes to > .. > A := Explode('-', 'ab-cd-ef'); > writeln(A[1]); // expect 'cd' > .. > > The inverse is accomplished by using PHP like 'implode', which glues > all splitted parts back to a single string. > > Wolfram > > > > >> -----Ursprüngliche Nachricht----- >> Von: FPC-Pascal users discussions >> Gesendet: 10.07.07 13:04:31 >> An: FPC-Pascal users discussions >> Betreff: [fpc-pascal] splitting string into array >> > > > >> Hi, >> >> is there any function in the libraries of fpc for splitting a string >> into an array naming the separator? >> >> In awk for eample if you do this: >> >> split("ab-cd-ef", x, "-") >> print x[2] >> >> it would split up the first string using "-" as separator and print >> >> cd >> >> to the output. That's what I'm searching for. >> In pascal. ;) >> >> TIA, >> Marc >> >> >> _______________________________________________ >> fpc-pascal maillist - >> http://lists.freepascal.org/mailman/listinfo/fpc-pascal >> >> > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Marc Santhoff
to Andrea Mauri: I used this, check it. // Returns an array with the parts of "str" separated by…
Andrea Mauri wrote 29 lines
I used this, check it. // Returns an array with the parts of "str" separated by "separator" function Split(const str: string; const separator: string): array of string; var i, n: integer; strline, strfield: string; begin n:= Occurs(str, separator); SetLength(Result, n + 1); i := 0; strline:= str; repeat if Pos(separator, strline) > 0 then begin strfield:= Copy(strline, 1, Pos(separator, strline) - 1); strline:= Copy(strline, Pos(separator, strline) + 1, Length(strline) - pos(separator,strline)); end else begin strfield:= strline; strline:= ''; end; Result[i]:= strfield; Inc(i); until strline= ''; if Result[High(Result)] = '' then SetLength(Result, Length(Result) -1); end;

Pretty cool, thank you very much.

Show quoted text 6 lines
andrea Wolfram Kläger ha scritto: > Here is a Delphi implementation of the common PHP function 'explode'. > > http://www.michael-puff.de/Developer/Delphi/Code-Snippets/Explode.html

I'll look at that one, too. Maybe someday my arrays grow and speed becomes an issue - better to check which one is fastest.

Wouldn't this function be a candidate for crawling into the 'strutils' unit?

Marc

Reply by email

L
Marc Santhoff wrote
Hi, is there any function in the libraries of fpc for splitting a string into an array naming the separator?

There is a function in the substrings.pas unit included in this package:

http://z505.com/cgi-bin/powtils/docs/1.6/idx.cgi?file=substrsplit&unit=substrings

And some other goodies in the substrings unit, and also some more goodies in strfilter.pas, and strwrap1.pas.

Many functions should be merged into an FPC rtl unit I suppose, since it appears many of us are reinventing the wheel each time rolling our own private units.

Reply by email

Michael Van Canneyt
to L
Show quoted text 16 lines
Marc Santhoff wrote: > Hi, > > is there any function in the libraries of fpc for splitting a string > into an array naming the separator? There is a function in the substrings.pas unit included in this package: http://z505.com/cgi-bin/powtils/docs/1.6/idx.cgi?file=substrsplit&unit=substrings And some other goodies in the substrings unit, and also some more goodies in strfilter.pas, and strwrap1.pas. Many functions should be merged into an FPC rtl unit I suppose, since it appears many of us are reinventing the wheel each time rolling our own private units.

There are such units: strutils, math, dateutils.

I think there is room for a few more:
fileutils (file/disk related),
osutils (getting os-specific data, versions and the like) classutils: additional functionality on top of the classes unit.

Feel free to make proposals. I guess the main problem will be the interface and error reporting: each has his own way of doing things, which others do not like or would do differently...

Michael.

Reply by email

Michael Van Canneyt
to Marc Santhoff: Pretty cool, thank you very much. I'll look at that one, too. Maybe someday my arrays…
Marc Santhoff wrote 45 lines
Am Dienstag, den 10.07.2007, 14:56 +0200 schrieb Andrea Mauri: > I used this, check it. > > // Returns an array with the parts of "str" separated by "separator" > function Split(const str: string; const separator: string): array of string; > var > i, n: integer; > strline, strfield: string; > begin > n:= Occurs(str, separator); > SetLength(Result, n + 1); > i := 0; > strline:= str; > repeat > if Pos(separator, strline) > 0 then > begin > strfield:= Copy(strline, 1, Pos(separator, strline) - 1); > strline:= Copy(strline, Pos(separator, strline) + 1, > Length(strline) - pos(separator,strline)); > end > else > begin > strfield:= strline; > strline:= ''; > end; > Result[i]:= strfield; > Inc(i); > until strline= ''; > if Result[High(Result)] = '' then SetLength(Result, Length(Result) -1); > end; Pretty cool, thank you very much. > andrea > > Wolfram Kläger ha scritto: > > Here is a Delphi implementation of the common PHP function 'explode'. > > > > http://www.michael-puff.de/Developer/Delphi/Code-Snippets/Explode.html I'll look at that one, too. Maybe someday my arrays grow and speed becomes an issue - better to check which one is fastest. Wouldn't this function be a candidate for crawling into the 'strutils' unit?

Probably, but I would change the interface:

function Split(const str: string; const separator: string; var Res : array of string) : Integer;

So the function returns the number of elements in the array. The function could also use some speedup. Deleting the parts which are no longer needed causes a lot of memory fragmentation.

Michael.

Reply by email

Marc Santhoff
to Michael Van Canneyt
Michael Van Canneyt wrote
On Tue, 10 Jul 2007, Marc Santhoff wrote:

[...]

Show quoted text 10 lines
> Wouldn't this function be a candidate for crawling into the 'strutils' > unit? Probably, but I would change the interface: function Split(const str: string; const separator: string; var Res : array of string) : Integer; So the function returns the number of elements in the array. The function could also use some speedup. Deleting the parts which are no longer needed causes a lot of memory fragmentation.

I'd second your opinion about the interface, but regarding speedup and memory fragmentation makes me think.

For speed I'd need some hints, what technique would be faster/fastest?

And for memory fragmentation: avoiding Copy could be done by using pointers running over the input string, or is there an even better approach?

Marc (not having found any information about 'this is faster than that' ;)

Reply by email

L
Show quoted text 6 lines
> > Wouldn't this function be a candidate for crawling into the 'strutils' > > unit? > > Probably, but I would change the interface: > > function Split(const str: string; const separator: string; var Res : array

of

Show quoted text 10 lines
> string) : Integer; > > So the function returns the number of elements in the array. > The function could also use some speedup. Deleting the parts > which are no longer needed causes a lot of memory fragmentation. I'd second your opinion about the interface, but regarding speedup and memory fragmentation makes me think. For speed I'd need some hints, what technique would be faster/fastest?

[HUMOR ON]

This is not good. All you asked for was a clean function that did a job. Then you had some people come in and *assume that there was a bottleneck* in your application, which was never indeed ever stated.

Knuth, are you there? Knuth!!!! Are you there?

I'm going to take a wild guess here...
Most of the time when programmers need to split a string into an array, it is fairly small strings.
Not often would one have a huge 500MB string with millions of delimiters in them. If one does have a 500MB string with millions of delimiters in them, THEN WE worry about optimization.

ON THE OTHER HAND... if it is a case that some people quite often are splitting up large strings.. and if Knuth was wrong... then... I ponder possibly using something called a CapArray which is like my CapString algorithm. Preset the array to about or 100 (or 500 if you anticipate it.. the initial capacitance).. and grow the array chunk by chunk while the single pass parser eats up the strings between delimitters and throws them into the array. Only one chunk growth is needed if the capacitance is estimated correctly or near correctly. Instead of using the Occurs() function which means that a double pass parser is needed.. it could instead be a single pass parser with the array items being added to the CapArray one by one, only triggering chunk growth if the array capacitance becomes filled. When the items are finished being added to the caparray, the caparray is set back to the count strings that was incremented while parsing.

Or one could use several stack based Fixed arrays.. for example array[0 to 99] if you only anticipate 100 .. but if there are more than 100, then pop another array2 open using a pointer to the first array (second array is on the heap, but at least the first one wasn't).

But, But But..No one has yet informed us that:

a) there is a bottleneck
b) the string will ever be large enough for any of the above optimizations to have ANY affect

Take for example if we were splitting an HTTP request string of some sort

somedata;somedata2;somedata3;

or

somedata=ccc&somedata2=bbb&somedata3=aaa

We only have to chop it three times by the ampersands, and then split it once by equal signs..
Making three or six setlength calls isn't going to kill anybody. That's the least of your worries.

It would be a worry if you had a huge stream of text.. like a 500MB file, yes. Who said we had a 500mb file? Who has done a survey showing that splitting is usually done on 500MB files?

There's More..

But wait.. why use Array's, when a stringlist could be used instead?

Then our code becomes even more complex because someone has to allocate the stringlist with a create, and then someone has to free it. Hmm. Or, since arrays and stringlists are actually just poor forms of databases, maybe we should build the split function to pump out the data into an an SQL database instead of an array, as a premature databasization (kind of like a premature optimization). After all, if you have a 500MB file with millions of delimiters in it, this data surely needs to be managed, doesn't it?

But why? Maybe all the guy wanted was a simple array and maybe speed was the absolute last thing the guy was worrying about.

Okay, but this still helped me brainwash the idea of a CapArray, even if this all was just academic premature optimization. Plus, if it is fairly easy to optimize a function, i.e. it doesn't take much time, then it isn't so harmful to optimize it. Plus, it is fun to solve puzzles too, hence the shootout contest and all that stuff.

[HUMOR OFF]

Reply by email

Michael Van Canneyt
to L
Show quoted text 23 lines
> > > Wouldn't this function be a candidate for crawling into the 'strutils' > > > unit? > > > > Probably, but I would change the interface: > > > > function Split(const str: string; const separator: string; var Res : array of > > string) : Integer; > > > > So the function returns the number of elements in the array. > > The function could also use some speedup. Deleting the parts > > which are no longer needed causes a lot of memory fragmentation. > I'd second your opinion about the interface, but regarding speedup and > memory fragmentation makes me think. > > For speed I'd need some hints, what technique would be faster/fastest? [HUMOR ON] This is not good. All you asked for was a clean function that did a job. Then you had some people come in and *assume that there was a bottleneck* in your application, which was never indeed ever stated.

I appreciate the humor :-)

But for the record:

I never assumed or said that there is a bottleneck in his application. I said that for inclusion in the RTL, the speedup would be needed, as the RTL is used in all kinds of situations, not only in his application.

Can you, BTW, explain the reference to Knuth ? I know who Donald Knuth is, but fail to see the link... ? (lack of culture on my part, I assume...)

Michael.

Reply by email

Marc Santhoff
to L: of [HUMOR ON] This is not good. All you asked for was a clean function that did a job.…
Show quoted text 19 lines
> > > Wouldn't this function be a candidate for crawling into the 'strutils' > > > unit? > > > > Probably, but I would change the interface: > > > > function Split(const str: string; const separator: string; var Res : array of > > string) : Integer; > > > > So the function returns the number of elements in the array. > > The function could also use some speedup. Deleting the parts > > which are no longer needed causes a lot of memory fragmentation. > I'd second your opinion about the interface, but regarding speedup and > memory fragmentation makes me think. > > For speed I'd need some hints, what technique would be faster/fastest? [HUMOR ON]

[...]

[HUMOR OFF]

Are you talking to me?

The question was not about algorithms but compiler internals.

Marc

Reply by email