Author Topic: Explode 2 - Function  (Read 6823 times)

0 Members and 1 Guest are viewing this topic.

Offline DorkeyDear

  • Veteran
  • *****
  • Posts: 1507
  • I also go by Curt or menturi
Explode 2 - Function
« on: August 10, 2009, 12:22:49 pm »
Script Name: Explode
Script Description A faster version of Split, aka XSplit
Authors: DorkeyDear, CurryWurst
Core Version: 2.6.5

Full Description:
After redoing my most recent Explode, CurryWurst and I made it much faster being over twice as fast as before!
Included is test code compared to my older version of Explode, with step by step modifications.
More statical numbers are available on Soldat Forums including the older XSplit.

Code: [Select]
function Explode(Source: string; const Delimiter: string): array of string;
var
  Position, DelLength, ResLength: integer;
begin
  DelLength := Length(Delimiter);
  Source := Source + Delimiter;
  repeat
    Position := Pos(Delimiter, Source);
    SetArrayLength(Result, ResLength + 1);
    Result[ResLength] := Copy(Source, 1, Position - 1);
    ResLength := ResLength + 1;
    Delete(Source, 1, Position + DelLength - 1);
  until (Position = 0);
  SetArrayLength(Result, ResLength - 1);
end;
CurryWurst  and I derived this with much experimentation.

Code: [Select]
function Explode(Source: string; const Delimiter: string): array of string;
var
  Position, DelLength, ResLength, CurResLength: integer;
begin
  DelLength := Length(Delimiter);
  Source := Source + Delimiter;
  CurResLength := 1;
  SetArrayLength(Result, 1);
  repeat
    Position := Pos(Delimiter, Source);
    if (CurResLength = ResLength) then begin
      CurResLength := 2 * CurResLength;
      SetArrayLength(Result, CurResLength);
    end;
    Result[ResLength] := Copy(Source, 1, Position - 1);
    ResLength := ResLength + 1;
    Delete(Source, 1, Position + DelLength - 1);
  until (Position = 0);
  SetArrayLength(Result, ResLength - 1);
end;
I derived this based off the previous version. This is faster in only limited cases. Use this if you expect the resulting array to be pretty large; like over 256 elements (actual value may (or may not) vary from machine to machine; I'm not very educated when it comes to that sort of thing). Changing the magic number 2 may cause the 256 magic number to vary. It all depends. On my machine when testing with this setup, having around 256 items seemed to have both versions take the same amount of time.
« Last Edit: August 27, 2011, 10:07:24 pm by DorkeyDear »

Offline -Bendarr-

  • Soldier
  • **
  • Posts: 104
Re: Explode 2 - Function
« Reply #1 on: August 10, 2009, 02:16:00 pm »
This is truly a lot better than XSplit.. People who use XSplit should paste Explode over their old split function.

Offline DorkeyDear

  • Veteran
  • *****
  • Posts: 1507
  • I also go by Curt or menturi
Re: Explode 2 - Function
« Reply #2 on: August 10, 2009, 02:31:05 pm »
After even more testing with the help of CurryWurst, we have came up with an even faster version. We cannot think to make this any faster than it already is.
« Last Edit: August 10, 2009, 02:42:05 pm by DorkeyDear »

Offline utkesmer

  • Major(1)
  • Posts: 44
Re: Explode 2 - Function
« Reply #3 on: June 01, 2011, 01:04:42 pm »
When the position is zero, the "repeat" part doesn't get broken. It is repeating the all things below after the position becomes zero.

Code: [Select]
SetArrayLength(Result, ResLength + 1);
Result[ResLength] := Copy(Source, 1, Position - 1);
ResLength := ResLength + 1;
Delete(Source, 1, Position + DelLength - 1);

Because, it checks whether position is zero, when it finishes repeating the whole "repeat" part.

For example, let's write all lines of a text file which has three lines in it.

Code: [Select]
... other codes...

for i := 0 to (GetArrayLength(X)-1) do begin
  WriteConsole(ID, X[i], RGB(255,215,0));
end;

...other codes...

The output is:

Code: [Select]
[*] first line
[*] second line
[*] third line
[*] <nothing>

It generates an empty line at the end. So you have to write (GetArrayLength(X)-2) instead of (GetArrayLength(X)-1).

This means that the length of the array is being one more than what it is supposed to be.

So I edited it like this:

Code: [Select]
function Explode(Source: string; const Delimiter: string): array of string;
var
  Position, DelLength, ResLength: integer;
begin
  DelLength := Length(Delimiter);
  Source := Source + Delimiter;
  Position := Pos(Delimiter, Source);   <<<<<<<<<<<<<<<<<<<<<<<<
  repeat
    SetArrayLength(Result, ResLength + 1);
    Result[ResLength] := Copy(Source, 1, Position - 1);
    ResLength := ResLength + 1;
    Delete(Source, 1, Position + DelLength - 1);
    Position := Pos(Delimiter, Source);   <<<<<<<<<<<<<<<<<<<<<<<<
  until (Position = 0);
  SetArrayLength(Result, ResLength - 1);
end;

Shouldn't it be like above?

Actually, this edition above might be more slow than the original, I really don't know but probably it is, whatever. Then let's edit just the last line of the function like this:

Code: [Select]
SetArrayLength(Result, ResLength - 2);
... instead of:

Code: [Select]
SetArrayLength(Result, ResLength - 1);
Sooo, what do you think? :)

Sorry for my grammar by the way.
« Last Edit: June 01, 2011, 01:06:23 pm by utkesmer »

Offline tk

  • Soldier
  • **
  • Posts: 235
Re: Explode 2 - Function
« Reply #4 on: June 01, 2011, 01:45:30 pm »
Never had such problems with this function, maybe you have a delimiter at the end of the exploded text and that's where the empty element comes from

Offline utkesmer

  • Major(1)
  • Posts: 44
Re: Explode 2 - Function
« Reply #5 on: June 01, 2011, 01:52:12 pm »
Never had such problems with this function, maybe you have a delimiter at the end of the exploded text and that's where the empty element comes from

No I tried both with and without delimiter (at the end), no difference.

Offline dnmr

  • Camper
  • ***
  • Posts: 315
  • emotionally handicapped
Re: Explode 2 - Function
« Reply #6 on: June 01, 2011, 04:00:51 pm »
doesnt readfile add #13#10 in the end of the result string?

Offline utkesmer

  • Major(1)
  • Posts: 44
Re: Explode 2 - Function
« Reply #7 on: June 01, 2011, 04:43:07 pm »
doesnt readfile add #13#10 in the end of the result string?

I don't know but it probably does because otherwise Explode wouldn't be able to get the last line.
« Last Edit: June 01, 2011, 04:44:47 pm by utkesmer »

Offline ExHunter

  • Inactive Soldat Developer
  • Soldier
  • ******
  • Posts: 154
  • Speedy go!
Re: Explode 2 - Function
« Reply #8 on: June 02, 2011, 07:38:34 am »
Yes dnmr, it does.

Offline CurryWurst

  • Camper
  • ***
  • Posts: 265
    • Soldat Global Account System
Re: Explode 2 - Function
« Reply #9 on: September 25, 2012, 01:58:36 pm »
doesnt readfile add #13#10 in the end of the result string?

I don't know but it probably does because otherwise Explode wouldn't be able to get the last line.

On behalf of your IRC request I reviewed the code and did some tests. To put the results in a nutshell I did not spot any misbehaviour. As tk, dnmr and ExHunter correctly imply and even explain, it only happens if you use the ReadFile() function which reflects proper behaviour.
If you still think the function does not work as expected, I would appreciate if you may provide some test scripts to reproduce the issues you encounter.

Thanks for your feedback.

Markus
« Last Edit: September 25, 2012, 02:01:21 pm by CurryWurst »
Soldat Global Account System: #soldat.sgas @ quakenet