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
- El parámetro aMax limita el número de cadenas que se devolverán
- 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.