2015-05-10 4 views
5

Wie soll ein Array von String in String konvertiert werden (mit Trennzeichen)? Ich meine, gibt es eine Systemfunktion, die ich verwenden kann, anstatt meine eigene Funktion zu schreiben?Wie verkettet man ein Array von String-Elementen zu einem String?

+2

Welche Delphi-Version? –

+0

@KenWhite: Version ist Delphi2007 – Hwau

+0

Sie können TStringList mit Delimiter verwenden. Oder Sie können Ihre eigene Funktion schreiben. Ich würde TStringList meiden. Keine Notwendigkeit, eine Instanz dafür zu machen. –

Antwort

4

Da Sie mit Delphi 2007 Sie haben es Ihnen selbst zu tun:

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; 

einfach das Array durchlaufen und verketten es mit Ihren seperator.

Und ein kleines Testbeispiel:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Caption :=StrArrayJoin(['This', 'is', 'a', 'test'], ' '); 
end; 
+1

Ich habe meine eigene Funktion geschrieben! Danke für den Vorschlag! – Hwau

+0

Nicht ideal in Bezug auf Geschwindigkeit –

2

In Delphi für .NET können Sie das Framework Join Funktion verwenden, während Sie die Open Source-JCL-Bibliothek verknüpfen können, wenn Sie sich nicht auf das .NET-Framework verlassen möchten: Werfen Sie einen Blick auf die IJclStringList interface der Bibliothek .

JclStringList.Join(','); 

Sonst wie jemand in den Kommentaren vorgeschlagen können Sie einfach eine TStringList auf diese Weise verwenden:

arrayList.Delimiter := ','; 
arrayList.QuoteChar := ''; 
joinedArray := arrayList.DelimitedText; 

Beachten Sie, dass neueste Version von Delphi XEs (seit XE3, wenn ich mich recht erinnere) eine TStringHelper Klasse, die die Join Methode der String-Klasse fügt hinzu:

class function Join(const Separator: string; const Values: 
IEnumerator<string>): string; overload; static; 
+1

Sie möchten die 'Join'-Überladung, die ein offenes Array von' string' akzeptiert. Natürlich ist 'Join', das Teil des String-Helfers ist, sehr schlecht implementiert. Die 'IEnumerable ' Version ist bis XE8 defekt, und die Effizienz ist schlecht. Es ist frustrierend, dass die aktuelle RTL-Qualität von Emba so schlecht ist. –

3

Die akzeptierte Antwort in Bezug auf die Geschwindigkeit ist nicht ideal, vor allem, wenn mehrere Threads verwendet werden. Dieser Ansatz ist im Einzelkern 3-mal schneller und skaliert gut auf 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; 

Geschwindigkeitstest:

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. 

Ergebnisse: auf einem Quad-Core-CPU JoinStrings ist 12x schneller.

StrArrayJoin 1 thread: 55 
JoinStrings 1 thread: 184 
StrArrayJoin 4 threads: 58 
JoinStrings 4 threads: 713 
Verwandte Themen