我試圖找到一個Delphi函數將輸入字符串拆分爲基於分隔符的字符串數組。我在谷歌上發現了很多,但似乎都有他們自己的問題,我還沒有能夠讓他們工作。將字符串拆分爲基於分隔符的字符串數組
我只需要分割一個字符串,如: "word:doc,txt,docx"
到基於':'的數組中。結果將是 ['word', 'doc,txt,docx']
。
有沒有人有他們知道的功能?
謝謝
我試圖找到一個Delphi函數將輸入字符串拆分爲基於分隔符的字符串數組。我在谷歌上發現了很多,但似乎都有他們自己的問題,我還沒有能夠讓他們工作。將字符串拆分爲基於分隔符的字符串數組
我只需要分割一個字符串,如: "word:doc,txt,docx"
到基於':'的數組中。結果將是 ['word', 'doc,txt,docx']
。
有沒有人有他們知道的功能?
謝謝
可以使用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.
UPDATE
爲StrictDelimiter
的說明,請參見本link。
Here是爆炸功能的實現是在很多其他編程語言作爲標準功能可供選擇:
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);
在這段代碼中有一些奇怪的和潛在的非常低效的選擇來管理/預測結果的長度。通過逐步增加結果數組,增加了內存重新分配和分段的機會。更有效率的做法是設置一個初始長度儘可能大,即假設輸入字符串由50%分隔符字符串=長度(S)div(2 *長度(分隔符)組成),然後將其設置爲實際的數量項目完成後1分配後可能是一個截斷 – Deltics 2010-04-12 23:54:40
你也沒有解釋Limit參數的目的我直觀地期望它設置一個最大數量的子字符串,實際上它似乎是約束檢測將子字符串轉換爲輸入字符串中第一個「Limit」字符數,這似乎毫無意義,因爲如果您需要這樣做,您可以簡單地通過所需子字符串的Copy()操作Explode()。子字符串會更加有用 – Deltics 2010-04-12 23:56:02
@Deltics:沒有人聲稱這是一個高度優化的函數,沒有人要求,所以我有點不理解你的抱怨,但也許你是其中的一員誰優化了一切,無論是否有必要... – Leo 2010-04-14 11:28:57
到爆炸()功能通過MEF提供的,但有幾個(其中我認爲一個bug修復的)差異類似:
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
它是尾部分隔和名義上的「空最後一個要素」,我認爲bug修復。 (我錯誤地建議輸入字符串最多可能包含50%的分隔符,但它當然可以包含100%的分隔符字符串,產生一個空元素數組) !)
德爾福2010年StrUtils.SplitString
嗯,不是在我的Delphi 2010版本中(XMLDoc和Indy單元IdStrings中有一個SplitString例程,但這些都不做海報想要的,XMLDoc例程也不會通過單元接口公開)。 – Deltics 2010-04-13 21:06:03
函數SplitString(const S,Delimiters:string):TStringDynArray;在StrUtils.pas中定義 – alex 2010-07-27 10:07:58
我無法包含文件StrUtils.pas(即使存在)。 – truthseeker 2012-02-01 08:26:18
我總是用類似這樣的東西:
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;
無需工程改造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'
爆炸是非常高的速度的功能,源alhoritm從字符串列表組分獲得。 我使用下一個測試爆炸: 爆炸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;
這不能編譯:「字符串」不是一個類型 – NGLN 2016-11-10 16:32:57
絕代碼庫提供了增強的StringList具有內置分割功能,即能夠既添加和替換現有的文本。它還提供參考計數界面。所以這可以用於舊的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:[email protected]@[email protected]
更復雜的例子:http://stackoverflow.com/a/14649862/976391 – 2013-02-26 16:53:36
你可以讓自己的函數返回字符串在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;
我寫了這個函數,它通過特定的分隔符返回分隔字符串的鏈表。純粹的免費pascal沒有模塊。
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;
使用SysUtils.TStringHelper.Split功能,在Delphi XE3介紹:
var
MyString: String;
Splitted: TArray<String>;
begin
MyString := 'word:doc,txt,docx';
Splitted := MyString.Split([':']);
end.
這將與給定的分隔符字符串分割成字符串數組。
只適用於utf-8句子 – Alper 2015-10-14 08:02:44
var
su : string; // What we want split
si : TStringList; // Result of splitting
Delimiter : string;
...
Delimiter := ';';
si.Text := ReplaceStr(su, Delimiter, #13#10);
線在SI列表將包含分裂字符串。
*
//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;
*
這比接受的答案好嗎? – MartynA 2017-01-20 22:54:24
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版本中存在一個錯誤(不確定哪個版本得到了修復),這會導致空格字符總是被**用作分隔符。所以小心處理! – Leo 2010-04-12 22:09:48
是的。您需要將StrictDelimiter設置爲true,並且如果StrictDelimiter屬性在您的Delphi版本中不可用,請不要使用此技術!但如果是這樣,那麼這是非常有用的。 – 2010-04-12 22:24:47
這不是一個錯誤,它是一個(令人討厭的)D1或D2設計決策方式。 CommaText應該用帶引號的空格來包圍任何字段。如果輸入在帶空格的字段周圍有雙引號,則結果是正確的。 – 2010-04-12 22:40:19