2012-04-02 15 views
1

Gibt es eine Möglichkeit, leere Zeichenfolgen aus dem dynamischen Array, das sich aus der SplitString-Funktion (Delphi XE, StrUtils) ergibt, auszuschließen, ohne das Array durchlaufen zu müssen?Eliminieren leerer Zeichenfolgen mit SplitString

Wenn nicht, kann jemand den effizientesten Weg vorschlagen? Im Moment mache ich es wie folgt aus:

function SplitStringNoEmpty(myString : string; myDelimiters : string):TStringDynArray; 
var 
    words_array_pre : TStringDynArray; 
    words_array_pos : TStringDynArray; 
    array_length : Integer; 
    actual_length : Integer; 
    current_word : string; 

    procedure AddElement(const Str: string); 
    begin 
     words_array_pos[actual_length]:= Str; 
     inc(actual_length); 
    end; 
begin 
    words_array_pre:= SplitString(myString, whitespaceNewLineCharacterSet + punctuationCharacterSet); 
    array_length:= Length(words_array_pre); 
    if (array_length >0) then 
    begin 
     actual_length:= 0; 
     SetLength(words_array_pos, array_length); 
     for current_word in words_array_pre do 
     begin 
     if (current_word <> '') then 
      AddElement(current_word); 
     end; 
     SetLength(words_array_pos, actual_length); 
     result:= words_array_pos; 
    end 
    else 
     result:= words_array_pre; 
end; 
+0

Haben Sie darüber nachgedacht, was gerade zu tun hat split, aber ohne im Ergebnis leere Elemente einschließlich? –

Antwort

2

Es ist unmöglich, bestimmte Elemente eines Arrays zu entfernen, ohne über das Array iterieren - wie sonst würden Sie wissen, welche Elemente zu entfernen? Die Verbesserungen, die an Ihrem Code vorgenommen werden müssen, sind die Notwendigkeit, ein extra Array zuzuordnen. Sie können das Original-Array in-place keulen:

function SplitStringNoEmpty(const s, delimiters: string): TStringDynArray; 
var 
    Src, Dest: Integer; 
begin 
    Result := SplitString(s, delimiters); 
    if Length(Result) <> 0 then begin 
    // Push all non-empty values to front of array 
    Dest := 0; 
    for Src := 0 to High(Result) do 
     if Result[Src] <> '' then begin 
     if Src <> Dest then 
      Result[Dest] := Result[Src]; 
     Inc(Dest); 
     end; 
    // Remove excess from end of array 
    SetLength(Result, Dest); 
    end; 
end; 
+0

Danke für die Optimierung Rob! StrUtils sollte eine ähnliche Funktion hinzugefügt werden. –

3

Sie können Ihre eigene Implementierung der Funktion split ignorieren die leeren Saiten schreiben.

prüfen diese Probe

function SplitString2(const S, Delimiters: string): TStringDynArray; 
var 
    LIndex, SIndex, FIndex, LMax, LPos: Integer; 
    foo : string; 
begin 
    Result := nil; 

    if S <> '' then 
    begin 
    LPos := 0; 
    LMax := 0; 
    SIndex := 1; 

    for LIndex := 1 to Length(S) do 
     if IsDelimiter(Delimiters, S, LIndex) then Inc(LMax); 

    SetLength(Result, LMax + 1); 

    repeat 
     FIndex := FindDelimiter(Delimiters, S, SIndex); 
     if FIndex <> 0 then 
     begin 
     foo:= Copy(S, SIndex, FIndex - SIndex); 
     if foo<>'' then 
     begin 
      Result[LPos] := foo; 
      Inc(LPos); 
     end; 
     SIndex := FIndex + 1; 
     end; 
    until (LPos = LMax) or (FIndex=0); 

    if LPos<LMax then 
    SetLength(Result, LPos + 1); 

    foo:=Copy(S, SIndex, Length(S) - SIndex + 1); 
    if foo<>'' then 
    Result[LMax] := foo 
    else 
    SetLength(Result, LPos); 
    end; 
end;