2012-04-02 81 views
1

有沒有辦法從SplitString函數(Delphi XE,StrUtils)產生的動態數組中排除空字符串,而不必遍歷數組?使用SplitString消除空白字符串

如果沒有,任何人都可以建議最有效的方法來做到這一點?現在我是這樣做的:

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

你有沒有考慮只是在做什麼SplitString做,但不包括在結果空元素? – 2012-04-02 20:16:02

回答

2

不可能刪除數組中的某些元素而無需迭代數組 - 您怎麼知道要刪除哪些元素?對代碼所作的改進是消除了分配額外陣列的需求。您可以原地挑選原始數組:

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

感謝Rob的優化! StrUtils應該添加一個類似的功能。 – 2012-04-02 20:22:28

3

您可以編寫自己的SplitString函數實現,忽略空字符串。

檢查該樣本

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;