Разделить строку на массив строк на основе разделителя
Я пытаюсь найти функцию Delphi, которая разделит входную строку на массив строк на основе разделителя. Я нашел много в Google, но у всех, похоже, есть свои проблемы, и я не смог заставить их работать.
мне нужно разделить строку:
"word:doc,txt,docx" в массив на основе ':'. Результат был бы
['word', 'doc,txt,docx'].
есть ли у кого-нибудь функция, которая, как они знают, работает?
спасибо
17 ответов:
вы можете использовать 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.обновление
посмотреть этот ссылке объяснение
StrictDelimiter.
можно использовать
StrUtils.SplitString.function SplitString(const S, Delimiters: string): TStringDynArray;описание от документация:
разбивает строку на части, разделенные указанным символ-разделитель.
SplitString разбивает строку на части, разделенные заданными символами-разделителями. S это строка, которая должна быть разделена. разделители - это строка, содержащая символы, определенные как разделители.
SplitString возвращает массив строк типа
С помощью командой sysutils.TStringHelper.Сплит функция, введенная в Delphi XE3:
var MyString: String; Splitted: TArray<String>; begin MyString := 'word:doc,txt,docx'; Splitted := MyString.Split([':']); end.это разделит строку с заданным разделителем на массив строк.
аналогично Explode () функция, предлагаемая Mef, но с несколькими отличиями (одно из которых я считаю исправлением ошибки):
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;отличия:
- параметр aMax ограничивает количество возвращаемых строк
- если входная строка заканчивается разделителем, то номинальная" пустая " конечная строка считается существующей
примеры:
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это трейлинг разделитель и условный "пустой последний элемент", который я считаю исправлением ошибки.
Я также включил изменение распределения памяти, которое я предложил, с уточнением (я ошибочно предположил, что входная строка может содержать не более 50% разделителей, но она может, конечно, состоять из 100% разделителей строк, давая массив пустых элементов!)
Я всегда использую что-то вроде этого:
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;
взорвать очень высокая скорость функция, источник alhoritm получить от компонента 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;
var su : string; // What we want split si : TStringList; // Result of splitting Delimiter : string; ... Delimiter := ';'; si.Text := ReplaceStr(su, Delimiter, #13#10);строки si список будет содержать разделенные строки.
здесь реализация функции разнесения, которая имеется во многих других языках программирования в качестве стандартной функции:
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;пример использования:
var res: TStringDynArray; begin res := Explode(':', yourString);
вы можете сделать свою собственную функцию, которая возвращает 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;
Я написал эту функцию, которая возвращает связанный список строк, разделенных по определенным разделителем. Чистый бесплатный Паскаль без модулей.
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.
Это решит вашу проблему
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;
библиотека кода Jedi предоставляет расширенный список строк со встроенной функцией разделения, которая способна как добавлять, так и заменять существующий текст. Он также предоставляет интерфейс с подсчетом ссылок. Таким образом, это можно использовать даже с более старыми версиями Delphi, которые не имеют расщеплений и без тщательных и немного утомительных настроек stock TStringList для использования только указанных разделителей.
например, данный текстовый файл строк, таких как
Dog 5 4 7их можно разобрать использование: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
основание ответа NGLG https://stackoverflow.com/a/8811242/6619626 Вы можете использовать следующую функцию:
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;он работает во всех версиях Delphi.
моя любимая функция для sliting:
procedure splitString(delim: char; s: string; ListOfStrings: TStrings); var temp: string; i: integer; begin ListOfStrings.Clear; for i:=1 to length(s) do begin if s[i] = delim then begin ListOfStrings.add(temp); temp := ''; end else begin temp := temp + s[i]; end; end; end;
*
//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;*
для delphi 2010 необходимо создать собственную функцию разделения.
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;вы можете ссылаться на него как таковой
type TStringArray = array of string; var Temp2:TStringArray; Temp1="hello:world"; Temp2=Split(Temp1,':')
Comments