根据分隔符将字符串拆分为字符串数组

Rya*_*yan 79 delphi string split delimiter

我正在尝试找到一个Delphi函数,它将输入字符串拆分为基于分隔符的字符串数组.我在谷歌上找到了很多,但似乎都有自己的问题,而我却无法让它们发挥作用.

我只需要将一个字符串拆分为: "word:doc,txt,docx"基于':'的数组.结果将是 ['word', 'doc,txt,docx'].

有没有人有他们知道的功能?

谢谢

RRU*_*RUZ 79

您可以使用TStrings.DelimitedText属性拆分字符串

检查这个样本

program Project28;

{$APPTYPE CONSOLE}

uses
  Classes,
  SysUtils;

procedure Split(Delimiter: Char; Str: string; ListOfStrings: TStrings) ;
begin
   ListOfStrings.Clear;
   ListOfStrings.Delimiter       := Delimiter;
   ListOfStrings.StrictDelimiter := True; // Requires D2006 or newer.
   ListOfStrings.DelimitedText   := Str;
end;


var
   OutPutList: TStringList;
begin
   OutPutList := TStringList.Create;
   try
     Split(':', 'word:doc,txt,docx', OutPutList) ;
     Writeln(OutPutList.Text);
     Readln;
   finally
     OutPutList.Free;
   end;
end.
Run Code Online (Sandbox Code Playgroud)

UPDATE

请参阅此链接以获取解释StrictDelimiter.

  • 不幸的是,许多"较旧"的Delphi版本中存在一个错误(不确定哪个版本得到了修复),其效果是空格字符**始终用作分隔符.所以要小心处理! (21认同)
  • 是啊.您需要将StrictDelimiter设置为true,如果您的Delphi版本中没有StrictDelimiter属性,请不要使用此技术!但如果是,那么这非常有用. (15认同)
  • 对于所有提出这个答案的人,请注意它不会产生问题中指定的数组.不完整的需求规范是这个行业的一个大问题,忽略了规定的要求并提供了没有要求的东西是另一个大问题.批准或者只是鼓励不良做法.;) (5认同)
  • 这不是一个错误,它是一个(恼人的)设计决策方式回到D1或D2.CommaText应该用带引号的空格括起任何字段.如果输入在带空格的任何字段周围有双引号,则结果是正确的. (3认同)

NGL*_*GLN 61

无需设计Split功能.它已经存在,见:Classes.ExtractStrings.

以下列方式使用它:

program Project1;

{$APPTYPE CONSOLE}

uses
  Classes;

var
  List: TStrings;
begin
  List := TStringList.Create;
  try
    ExtractStrings([':'], [], PChar('word:doc,txt,docx'), List);
    WriteLn(List.Text);
    ReadLn;
  finally
    List.Free;
  end;
end.
Run Code Online (Sandbox Code Playgroud)

并完全回答这个问题; List表示具有元素的所需数组:

List[0] = 'word'
List[1] = 'doc,txt,docx'
Run Code Online (Sandbox Code Playgroud)

  • ExtractStrings非常不灵活:"回车,换行字符和引号字符(单个或双重)始终被视为分隔符."; 和"注意:ExtractStrings不会向列表中添加空字符串." (13认同)

ale*_*lex 44

你可以用StrUtils.SplitString.

function SplitString(const S, Delimiters: string): TStringDynArray;
Run Code Online (Sandbox Code Playgroud)

它来自文档的描述:

将字符串拆分为由指定的分隔符分隔的不同部分.

SplitString将字符串拆分为由指定的分隔符分隔的不同部分.S是要拆分的字符串. 分隔符是一个字符串,包含定义为分隔符的字符.

SplitString返回System.Types.TStringDynArray类型的字符串数组,其中包含原始字符串的拆分部分.

  • 嗯,不是在我的Delphi 2010版本中(在XMLDoc和(Indy unit)IdStrings中有一个SplitString例程,但这些都不是海报想要的,而且XMLDoc例程也没有通过单元接口公开). (3认同)
  • function SplitString(const S,Delimiters:string):TStringDynArray; 在StrUtils.pas中定义 (3认同)

LU *_* RD 38

使用SysUtils.TStringHelper.Split功能,在Delphi XE3介绍:

var
  MyString: String;
  Splitted: TArray<String>;
begin
  MyString := 'word:doc,txt,docx';
  Splitted := MyString.Split([':']);
end.
Run Code Online (Sandbox Code Playgroud)

这会将具有给定分隔符的字符串拆分为字符串数组.


Fra*_*ank 16

我总是使用类似的东西:

Uses
   StrUtils, Classes;

Var
  Str, Delimiter : String;
begin
  // Str is the input string, Delimiter is the delimiter
  With TStringList.Create Do
  try
    Text := ReplaceText(S,Delim,#13#10);

    // From here on and until "finally", your desired result strings are
    // in strings[0].. strings[Count-1)

  finally
    Free; //Clean everything up, and liberate your memory ;-)
  end;

end;
Run Code Online (Sandbox Code Playgroud)

  • 对于旧版Delphi版用户来说,这是一个很好的解 (2认同)

Del*_*ics 13

类似于Mef提供的Explode()函数,但有一些差异(其中一个我认为是一个错误修复):

  type
    TArrayOfString = array of String;


  function SplitString(const aSeparator, aString: String; aMax: Integer = 0): TArrayOfString;
  var
    i, strt, cnt: Integer;
    sepLen: Integer;

    procedure AddString(aEnd: Integer = -1);
    var
      endPos: Integer;
    begin
      if (aEnd = -1) then
        endPos := i
      else
        endPos := aEnd + 1;

      if (strt < endPos) then
        result[cnt] := Copy(aString, strt, endPos - strt)
      else
        result[cnt] := '';

      Inc(cnt);
    end;

  begin
    if (aString = '') or (aMax < 0) then
    begin
      SetLength(result, 0);
      EXIT;
    end;

    if (aSeparator = '') then
    begin
      SetLength(result, 1);
      result[0] := aString;
      EXIT;
    end;

    sepLen := Length(aSeparator);
    SetLength(result, (Length(aString) div sepLen) + 1);

    i     := 1;
    strt  := i;
    cnt   := 0;
    while (i <= (Length(aString)- sepLen + 1)) do
    begin
      if (aString[i] = aSeparator[1]) then
        if (Copy(aString, i, sepLen) = aSeparator) then
        begin
          AddString;

          if (cnt = aMax) then
          begin
            SetLength(result, cnt);
            EXIT;
          end;

          Inc(i, sepLen - 1);
          strt := i + 1;
        end;

      Inc(i);
    end;

    AddString(Length(aString));

    SetLength(result, cnt);
  end;
Run Code Online (Sandbox Code Playgroud)

区别:

  1. aMax参数限制要返回的字符串数
  2. 如果输入字符串由分隔符终止,则认为存在标称"空"的最终字符串

例子:

SplitString(':', 'abc') returns      :    result[0]  = abc

SplitString(':', 'a:b:c:') returns   :    result[0]  = a
                                          result[1]  = b
                                          result[2]  = c
                                          result[3]  = <empty string>

SplitString(':', 'a:b:c:', 2) returns:    result[0]  = a
                                          result[1]  = b
Run Code Online (Sandbox Code Playgroud)

它是尾随分隔符和我认为错误修复的名义"空的最终元素".

我还整合了我建议的内存分配更改,并进行了细化(我错误地建议输入字符串最多可能包含50%的分隔符,但可以想象当然可以包含100%的分隔符字符串,从而产生一个空元素数组!)


小智 7

爆炸是一种非常高速的功能,源自altritm来自TStrings组件.我使用下一个测试爆炸:爆炸134217733字节的数据,我得到19173962个元素,工作时间:2984毫秒.

Implode是非常低速的功能,但我写得很容易.

{ ****************************************************************************** }
{  Explode/Implode (String <> String array)                                      }
{ ****************************************************************************** }
function Explode(S: String; Delimiter: Char): Strings; overload;
var I, C: Integer; P, P1: PChar;
begin
    SetLength(Result, 0);
    if Length(S) = 0 then Exit;
    P:=PChar(S+Delimiter); C:=0;
    while P^ <> #0 do begin
       P1:=P;
       while (P^ <> Delimiter) do P:=CharNext(P);
       Inc(C);
       while P^ in [#1..' '] do P:=CharNext(P);
       if P^ = Delimiter then begin
          repeat
           P:=CharNext(P);
          until not (P^ in [#1..' ']);
       end;
    end;
    SetLength(Result, C);
    P:=PChar(S+Delimiter); I:=-1;
    while P^ <> #0 do begin
       P1:=P;
       while (P^ <> Delimiter) do P:=CharNext(P);
       Inc(I); SetString(Result[I], P1, P-P1);
       while P^ in [#1..' '] do P:=CharNext(P);
       if P^ = Delimiter then begin
          repeat
           P:=CharNext(P);
          until not (P^ in [#1..' ']);
       end;
    end;
end;

function Explode(S: String; Delimiter: Char; Index: Integer): String; overload;
var I: Integer; P, P1: PChar;
begin
    if Length(S) = 0 then Exit;
    P:=PChar(S+Delimiter); I:=1;
    while P^ <> #0 do begin
       P1:=P;
       while (P^ <> Delimiter) do P:=CharNext(P);
        SetString(Result, P1, P-P1);
        if (I <> Index) then Inc(I) else begin
           SetString(Result, P1, P-P1); Exit;
        end;
       while P^ in [#1..' '] do P:=CharNext(P);
       if P^ = Delimiter then begin
          repeat
           P:=CharNext(P);
          until not (P^ in [#1..' ']);
       end;
    end;
end;

function Implode(S: Strings; Delimiter: Char): String;
var iCount: Integer;
begin
     Result:='';
     if (Length(S) = 0) then Exit;
     for iCount:=0 to Length(S)-1 do
     Result:=Result+S[iCount]+Delimiter;
     System.Delete(Result, Length(Result), 1);
end;
Run Code Online (Sandbox Code Playgroud)

  • 这不编译:`字符串`不是一种类型. (3认同)

Iho*_*nko 7

var  
    su  : string;        // What we want split
    si  : TStringList;   // Result of splitting
    Delimiter : string;
    ...
    Delimiter := ';';
    si.Text := ReplaceStr(su, Delimiter, #13#10);
Run Code Online (Sandbox Code Playgroud)

在线路SI列表将包含劈裂字符串.


bob*_*ski 6

您可以创建自己的函数,返回字符串的TArray:

function mySplit(input: string): TArray<string>;
var
  delimiterSet: array [0 .. 0] of char; 
     // split works with char array, not a single char
begin
  delimiterSet[0] := '&'; // some character
  result := input.Split(delimiterSet);
end;
Run Code Online (Sandbox Code Playgroud)


Leo*_*Leo 5

是一个爆炸函数的实现,它作为标准函数在许多其他编程语言中可用:

type 
  TStringDynArray = array of String;

function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray; 
var 
  SepLen: Integer; 
  F, P: PChar; 
  ALen, Index: Integer; 
begin 
  SetLength(Result, 0); 
  if (S = '') or (Limit < 0) then Exit; 
  if Separator = '' then 
  begin 
    SetLength(Result, 1); 
    Result[0] := S; 
    Exit; 
  end; 
  SepLen := Length(Separator); 
  ALen := Limit; 
  SetLength(Result, ALen); 

  Index := 0; 
  P := PChar(S); 
  while P^ <> #0 do 
  begin 
    F := P; 
    P := AnsiStrPos(P, PChar(Separator)); 
    if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F); 
    if Index >= ALen then 
    begin 
      Inc(ALen, 5); 
      SetLength(Result, ALen); 
    end; 
    SetString(Result[Index], F, P - F); 
    Inc(Index); 
    if P^ <> #0 then Inc(P, SepLen); 
  end; 
  if Index < ALen then SetLength(Result, Index); 
end; 
Run Code Online (Sandbox Code Playgroud)

样品用法:

var
  res: TStringDynArray;
begin
  res := Explode(':', yourString);
Run Code Online (Sandbox Code Playgroud)

  • 在此代码中有一些奇怪且可能非常低效的选择,用于管理/预测结果的长度.通过递增地增加结果数组,增加了内存重新分配和分段的可能性.更高效的是设置一个尽可能大的初始长度,即假设输入字符串由50%的分隔符串= Length(S)div(2*Length(Separator))组成.然后将其设置为实际的完成后的项目.1分配后可能是一次截断. (2认同)

Ale*_*cur 5

我编写了这个函数,它通过特定的分隔符返回分隔字符串的链表.纯净自由帕斯卡没有模块.

Program split_f;

type
    PTItem = ^TItem;
    TItem = record
        str : string;
        next : PTItem;
    end;

var
    s : string;
    strs : PTItem;

procedure split(str : string;delim : char;var list : PTItem);
var
    i : integer;
    buff : PTItem;
begin
    new(list);
    buff:= list;
    buff^.str:='';
    buff^.next:=nil;

    for i:=1 to length(str) do begin
        if (str[i] = delim) then begin
            new(buff^.next);
            buff:=buff^.next;
            buff^.str := '';
            buff^.next := nil;
        end
        else
        buff^.str:= buff^.str+str[i];
    end;
end;

procedure print(var list:PTItem);
var
    buff : PTItem;
begin
    buff := list;
    while buff<>nil do begin
        writeln(buff^.str);
        buff:= buff^.next;
    end;
end;

begin

    s := 'Hi;how;are;you?';

    split(s, ';', strs);
    print(strs);


end.
Run Code Online (Sandbox Code Playgroud)