接受的答案在速度方面并不理想,尤其是在使用多个线程的情况下。这种方法在单核上的速度提高了 3 倍,并且可以在 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;
速度测试:
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.
结果:在四核 CPU 上,JoinStrings 的速度提高了 12 倍。
StrArrayJoin 1 thread: 55
JoinStrings 1 thread: 184
StrArrayJoin 4 threads: 58
JoinStrings 4 threads: 713