Я пытаюсь найти функцию Delphi, которая разделит входную строку на массив строк на основе разделителя. Я нашел много в Google, но у всех, похоже, есть свои проблемы, и мне не удалось заставить их работать.
Мне просто нужно разбить строку вроде:
"word:doc,txt,docx"
на массив на основе ':'. Результат был бы
['word', 'doc,txt,docx']
.
У кого-нибудь есть функция, которая, как они знают, работает?
Спасибо
Нет необходимости в разработке
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.
И чтобы ответить на вопрос полностью;
List
представляет желаемый массив с элементами:List[0] = 'word' List[1] = 'doc,txt,docx'
источник
split
функцию, а в необходимостиTStrings
объекта. И из-за негибкости упоминаний (@awmross) я бы предпочел решение ФрэнкаВы можете использовать
StrUtils.SplitString
.function SplitString(const S, Delimiters: string): TStringDynArray;
Его описание из документации :
источник
Использование функции SysUtils.TStringHelper.Split , представленной в Delphi XE3:
var MyString: String; Splitted: TArray<String>; begin MyString := 'word:doc,txt,docx'; Splitted := MyString.Split([':']); end.
Это разделит строку с заданным разделителем на массив строк.
источник
Я всегда использую что-то подобное:
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;
источник
Strutils::AnsiReplaceText
list.Text := AnsiReplaceStr(source, delimiter, #13#10);
.Подобна функции 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;
Отличия:
Примеры:
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% строк разделителей, что дает массив пустых элементов!)
источник
Explode - очень высокоскоростная функция, исходный алгоритм которой можно получить из компонента TStrings. Я использую следующий тест для взрыва: Explode 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;
источник
Strings
это не тип.var su : string; // What we want split si : TStringList; // Result of splitting Delimiter : string; ... Delimiter := ';'; si.Text := ReplaceStr(su, Delimiter, #13#10);
Строки в списке si будут содержать разделенные строки.
источник
Вы можете создать свою собственную функцию, которая возвращает 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;
источник
Вот реализация функции разнесения, которая доступна во многих других языках программирования как стандартная функция:
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);
источник
Я написал эту функцию, которая возвращает связанный список строк, разделенных определенным разделителем. Чистый бесплатный паскаль без модулей.
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.
источник
Библиотека Jedi Code Library предоставляет расширенный StringList со встроенной функцией Split, которая способна как добавлять, так и заменять существующий текст. Он также предоставляет интерфейс с подсчетом ссылок. Таким образом, это можно использовать даже со старыми версиями Delphi, в которых нет SplitStrings, и без осторожной и немного утомительной настройки стандартного 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
источник
Это решит вашу проблему
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;
источник
Моя любимая функция для разделения:
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]; if i=length(s) then ListOfStrings.add(temp); end; end; ListOfStrings.add(temp); end;
источник
ListOfStrings.add(temp);
после цикла, чтобы добавить последний элемент.*
//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;
*
источник
В базе ответа 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.
источник
Для 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,':')
источник
procedure SplitCSV(S:STRING;out SL:TStringList); var c,commatext:string; a,b,up:integer; begin c:=s.Replace(' ','<SPACE>'); //curate spaces //first ocurrence of " a:=pos('"',c); b:=pos('"',c,a+1); if (a>0) and (b>0) then begin commatext:=commatext+copy(c,0,a-1); commatext:=commatext+copy(c,a,b-a+1).Replace(',','<COMMA>'); //curate commas up:=b+1; end else commatext:=c; //while continue discovering " while (a>0) and (b>0) do begin a:=Pos('"',c,b+1); b:=pos('"',c,a+1); if (a>0) and (b>0) then begin commatext:=commatext+copy(c,up,a-up); commatext:=commatext+copy(c,a,b-a+1).Replace(',','<COMMA>'); //curate commas up:=b+1; end; end; //last piece of text end if up<c.Length then commatext:=commatext+copy(c,up,c.Length-up+1); //split text using CommaText sl.CommaText:=commatext; sl.Text:=sl.Text.Replace('<COMMA>',','); //curate commas sl.Text:=sl.Text.Replace('<SPACE>',' '); //curate spaces end;
источник
interface uses Classes; type TStringArray = array of string; TUtilStr = class class function Split(const AValue: string; const ADelimiter: Char = ';'; const AQuoteChar: Char = '"'): TStringArray; static; end; implementation { TUtilStr } class function TUtilStr.Split(const AValue: string; const ADelimiter: Char; const AQuoteChar: Char): TStringArray; var LSplited: TStringList; LText: string; LIndex: Integer; begin LSplited := TStringList.Create; try LSplited.StrictDelimiter := True; LSplited.Delimiter := ADelimiter; LSplited.QuoteChar := AQuoteChar; LSplited.DelimitedText := AValue; SetLength(Result, LSplited.Count); for LIndex := 0 to LSplited.Count - 1 do begin Result[LIndex] := LSplited[LIndex]; end; finally LSplited.Free; end; end; end.
источник