funcion array delphi string split delimiter

delphi - array - Divida una cadena en una matriz de cadenas basada en un delimitador



split string delphi (16)

Estoy intentando encontrar una función Delphi que dividirá una cadena de entrada en una matriz de cadenas basadas en un delimitador. He encontrado mucho en Google, pero todos parecen tener sus propios problemas y no he podido hacer que ninguno funcione.

Solo necesito dividir una cadena como: "word:doc,txt,docx" en una matriz basada en '':''. El resultado sería [''word'', ''doc,txt,docx''] .

¿Alguien tiene una función que saben que funciona?

Gracias


*

//Basic functionality of a TStringList solves this: uses Classes //TStringList ,types //TStringDynArray ,SysUtils //StringReplace() ; .... //-------------------------------------------------------------------------- function _SplitString(const s:string; const delimiter:Char):TStringDynArray; var sl:TStringList; i:integer; begin sl:=TStringList.Create; //separete delimited items by sLineBreak;TStringlist will do the job: sl.Text:=StringReplace(s,delimiter,sLineBreak,[rfReplaceAll]); //return the splitted string as an array: setlength(Result,sl.count); for i:=0 to sl.Count-1 do Result[i]:=sl[i]; sl.Free; end; //To split a FileName (last item will be the pure filename itselfs): function _SplitPath(const fn:TFileName):TStringDynArray; begin result:=_SplitString(fn,''/'); end;

*


Escribí esta función que devuelve una lista vinculada de cadenas separadas por un delimitador específico. Pascal puro sin módulos.

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.


Esto resolverá su problema

interface TArrayStr = Array Of string; implementation function SplitString(Text: String): TArrayStr; var intIdx: Integer; intIdxOutput: Integer; const Delimiter = '';''; begin intIdxOutput := 0; SetLength(Result, 1); Result[0] := ''''; for intIdx := 1 to Length(Text) do begin if Text[intIdx] = Delimiter then begin intIdxOutput := intIdxOutput + 1; SetLength(Result, Length(Result) + 1); end else Result[intIdxOutput] := Result[intIdxOutput] + Text[intIdx]; end; end;


Explotar es una función de muy alta velocidad, fuente alhoritm obtener del componente TStrings. Uso la siguiente prueba para explotar: explotar 134217733 bytes de datos, obtengo 19173962 elementos, tiempo de trabajo: 2984 ms.

Implode es una función de muy baja velocidad, pero lo escribo fácil.

{ ****************************************************************************** } { 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;


Jedi Code Library proporciona una StringList mejorada con función Split incorporada, que es capaz de agregar y reemplazar el texto existente. También proporciona una interfaz contada por referencia. Por lo tanto, esto se puede usar incluso con versiones anteriores de Delphi que no tienen SplitStrings y sin personalizaciones cuidadosas y un poco tediosas del stock TStringList para usar solo delimitadores específicos.

Por ejemplo, un archivo de texto dado de líneas como Dog 5 4 7 se puede analizar usando:

var slF, slR: IJclStringList; ai: TList<integer>; s: string; i: integer; action: procedure(const Name: string; Const Data: array of integer); slF := TJclStringList.Create; slF.LoadFromFile(''some.txt''); slR := TJclStringList.Create; for s in slF do begin slR.Split(s, '' '', true); ai := TList<Integer>.Create; try for i := 1 to slR.Count - 1 do ai.Add(StrToInt(slR[i])); action(slR[0], ai.ToArray); finally ai.Free; end; end;

http://wiki.delphi-jedi.org/wiki/JCL_Help:IJclStringList.Split@string@string@Boolean


La base de NGLG answer https://.com/a/8811242/6619626 puede usar la siguiente función:

type OurArrayStr=array of string; function SplitString(DelimeterChars:char;Str:string):OurArrayStr; var seg: TStringList; i:integer; ret:OurArrayStr; begin seg := TStringList.Create; ExtractStrings([DelimeterChars],[], PChar(Str), seg); for i:=0 to seg.Count-1 do begin SetLength(ret,length(ret)+1); ret[length(ret)-1]:=seg.Strings[i]; end; SplitString:=ret; seg.Free; end;

Funciona en todas las versiones de Delphi.


No hay necesidad de diseñar una función Split . Ya existe, mira: Classes.ExtractStrings .

Úselo de la siguiente manera:

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.

Y para responder la pregunta completamente; List representa la matriz deseada con los elementos:

List[0] = ''word'' List[1] = ''doc,txt,docx''


Para Delphi 2010, necesita crear su propia función de división.

function Split(const Texto, Delimitador: string): TStringArray; var i: integer; Len: integer; PosStart: integer; PosDel: integer; TempText:string; begin i := 0; SetLength(Result, 1); Len := Length(Delimitador); PosStart := 1; PosDel := Pos(Delimitador, Texto); TempText:= Texto; while PosDel > 0 do begin Result[i] := Copy(TempText, PosStart, PosDel - PosStart); PosStart := PosDel + Len; TempText:=Copy(TempText, PosStart, Length(TempText)); PosDel := Pos(Delimitador, TempText); PosStart := 1; inc(i); SetLength(Result, i + 1); end; Result[i] := Copy(TempText, PosStart, Length(TempText)); end;

Puedes referirte a eso como tal

type TStringArray = array of string; var Temp2:TStringArray; Temp1="hello:world"; Temp2=Split(Temp1,'':'')


Puede hacer su propia función que devuelve TArray de cadena:

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;


Siempre uso algo similar a esto:

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;


Similar a la función Explode () ofrecida por Mef, pero con un par de diferencias (una de las cuales considero una solución de error):

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;

Diferencias

  1. El parámetro aMax limita el número de cadenas que se devolverán
  2. Si la secuencia de entrada finaliza con un separador, se considera que existe una cadena final nominal "vacía".

Ejemplos:

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

Es el separador final y el "elemento final vacío" nocional que considero la corrección de errores.

También incorporé el cambio de asignación de memoria que sugerí, con refinamiento (sugerí erróneamente que la cadena de entrada podría contener como máximo un 50% de separadores, pero posiblemente podría consistir en 100% de cadenas separadoras, produciendo una serie de elementos vacíos).


Usando la función SysUtils.TStringHelper.Split , presentada en Delphi XE3:

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

Esto dividirá una cadena con un delimitador dado en una matriz de cadenas.


puede usar la propiedad TStrings.DelimitedText para dividir una cadena

verifica esta muestra

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.

ACTUALIZAR

Vea este link para una explicación de StrictDelimiter .


Here hay una implementación de una función de explosión que está disponible en muchos otros lenguajes de programación como una función estándar:

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;

Uso de muestra:

var res: TStringDynArray; begin res := Explode('':'', yourString);


StrUtils.SplitString en Delphi 2010


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

Lines in si list contendrá cadenas divididas.