delphi - String.Split works strange when last value is empty -
i'd split string array works bad when last "value" empty. see example please. bug or feature? there way how use function without workarounds?
var arr: tarray<string>; arr:='a;b;c'.split([';']); //length of array = 3, it's ok arr:='a;b;c;'.split([';']); //length of array = 3, expect 4 arr:='a;b;;c'.split([';']); //length of array = 4 since empty value inside arr:=('a;b;c;'+' ').split([';']); //length of array = 4 (primitive workaround space)
this behaviour can't changed. there's no way customise how split function works. suspect you'll need provide own split implementation. michael erikkson helpfully points out in comment system.strutils.splitstring
behaves in manner desire.
the design seems me poor. instance
length('a;'.split([';'])) = 1
and yet
length(';a'.split([';'])) = 2
this asymmetry clear indication of poor design. it's astonishing testing did not identify this.
the fact design suspect means may worth submitting bug report. i'd expect denied since change impact existing code. never know.
my recommendations:
- use own split implementation performs require.
- submit bug report.
whilst system.strutils.splitstring
want, performance not great. not matter. in case should use it. however, if performance matters, offer this:
{$apptype console} uses system.sysutils, system.diagnostics, system.strutils; function mysplit(const s: string; separator: char): tarray<string>; var i, itemindex: integer; len: integer; separatorcount: integer; start: integer; begin len := length(s); if len=0 begin result := nil; exit; end; separatorcount := 0; := 1 len begin if s[i]=separator begin inc(separatorcount); end; end; setlength(result, separatorcount+1); itemindex := 0; start := 1; := 1 len begin if s[i]=separator begin result[itemindex] := copy(s, start, i-start); inc(itemindex); start := i+1; end; end; result[itemindex] := copy(s, start, len-start+1); end; const inputstring = 'asdkjhasd,we1324,wqweqw,qweqlkjh,asdqwe,qweqwe,asdasdqw'; var i: integer; stopwatch: tstopwatch; const count = 3000000; begin stopwatch := tstopwatch.startnew; := 1 count begin inputstring.split([',']); end; writeln('string.split: ', stopwatch.elapsedmilliseconds); stopwatch := tstopwatch.startnew; := 1 count begin system.strutils.splitstring(inputstring, ','); end; writeln('strutils.splitstring: ', stopwatch.elapsedmilliseconds); stopwatch := tstopwatch.startnew; := 1 count begin mysplit(inputstring, ','); end; writeln('mysplit: ', stopwatch.elapsedmilliseconds); end.
the output of 32 bit release build xe7 on e5530 is:
string.split: 2798 strutils.splitstring: 7167 mysplit: 1428
Comments
Post a Comment