The accepted answer is not ideal in terms of speed, especially if multiple streams are used. This approach is 3 times faster on a single core and scales well on SMP.
function JoinStrings(const s: array of string; Delimiter: Char): string; var i, c: Integer; p: PChar; begin c := 0; for i := 0 to High(s) do Inc(c, Length(s[i])); SetLength(Result, c + High(s)); p := PChar(Result); for i := 0 to High(s) do begin if i > 0 then begin p^ := Delimiter; Inc(p); end; Move(PChar(s[i])^, p^, SizeOf(Char)*Length(s[i])); Inc(p, Length(s[i])); end; end;
Speed ββtest:
program Project1; {$APPTYPE CONSOLE} uses Windows, SysUtils, StrUtils, Classes; function StrArrayJoin(const StringArray: array of string; const Separator: string) : string; var i : Integer; begin Result := ''; for i := low(StringArray) to high(StringArray) do Result := Result + StringArray[i] + Separator; Delete(Result, Length(Result), 1); end; function JoinStrings(const s: array of string; Delimiter: Char): string; var i, c: Integer; p: PChar; begin c := 0; for i := 0 to High(s) do Inc(c, Length(s[i])); SetLength(Result, c + High(s)); p := PChar(Result); for i := 0 to High(s) do begin if i > 0 then begin p^ := Delimiter; Inc(p); end; Move(PChar(s[i])^, p^, SizeOf(Char)*Length(s[i])); Inc(p, Length(s[i])); end; end; var TestData: array of string; type TTestThread = class(TThread) protected Func: Boolean; Count: Integer; procedure Execute; override; end; procedure TTestThread.Execute; var dtStart: TDateTime; i: Integer; begin dtStart := Now; Count := 0; repeat for i := 1 to 1000 do if Func then JoinStrings(TestData, ';') else StrArrayJoin(TestData, ';'); InterlockedIncrement(Count); until Now > dtStart + 1/86400; end; procedure TestSmp(CpuCount: Integer; Func: Boolean); var i, c: Integer; Threads: array of TTestThread; begin SetLength(Threads, CpuCount); for i := 0 to High(Threads) do begin Threads[i] := TTestThread.Create(true); Threads[i].Func := Func; Threads[i].Resume; end; c := 0; for i := 0 to High(Threads) do begin Threads[i].WaitFor; Inc(c, Threads[i].Count); Threads[i].Free; end; WriteLn(c); end; procedure Init(); var i: Integer; begin SetLength(TestData, 1000); for i := 0 to High(TestData) do TestData[i] := DupeString('x', Random(32)); end; begin try Init(); Assert(StrArrayJoin(TestData, ';') = JoinStrings(TestData, ';')); TestSmp(1, false); TestSmp(1, true); TestSmp(4, false); TestSmp(4, true); except on E:Exception do Writeln(E.Classname, ': ', E.Message); end; Readln; end.
Results: JoinStrings is 12 times faster on a quad-core processor.
StrArrayJoin 1 thread: 55 JoinStrings 1 thread: 184 StrArrayJoin 4 threads: 58 JoinStrings 4 threads: 713