Устранить пустые строки с помощью SplitString - PullRequest
1 голос
/ 02 апреля 2012

Есть ли способ исключить пустые строки из динамического массива, являющегося результатом функции SplitString (Delphi XE, StrUtils), без необходимости перебирать массив?

Если нет, может ли кто-нибудь предложить наиболее эффективныйспособ сделать это?Прямо сейчас я делаю это так:

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;

Ответы [ 2 ]

3 голосов
/ 03 апреля 2012

Вы можете написать собственную реализацию функции 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;
2 голосов
/ 03 апреля 2012

Невозможно удалить некоторые элементы массива без итерации по массиву - как еще вы знаете, какие элементы удалить? Улучшения, внесенные в ваш код, устраняют необходимость выделения массива extra . Вы можете удалить исходный массив на месте:

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;
...