2016-03-07 12 views
9

मैं का उपयोग TStringDynArray में स्ट्रिंग को विभाजित करने के लिए करता हूं, लेकिन आउटपुट की अपेक्षा नहीं की गई थी।स्ट्रूट्स। स्प्लिटस्ट्रिंग अपेक्षित काम नहीं कर रहा है

मैं एक स्ट्रिंग str है: 'a'; 'b'; 'c'
अब मैं StrUtils.SplitString(str, '; '); बुलाया स्ट्रिंग विभाजित करने के लिए और मैं तीन तत्वों के साथ एक सरणी की उम्मीद: मैं इस मुद्दे को समझाने की कोशिश करेंगे 'a', 'b', 'c'

लेकिन क्या मैं मिला पांच तत्वों के साथ एक सरणी: 'a', '', 'b', '', 'c'
जब मैं '; ' के बजाय ';' के साथ विभाजित करता हूं तो मुझे एक प्रमुख खाली के साथ तीन तत्व मिलते हैं।

तो मुझे अपने पहले समाधान में खाली तार क्यों मिलते हैं?

+3

दस्तावेज़ पढ़ें। शायद उम्मीद के अनुसार नहीं, लेकिन यह दस्तावेज के रूप में काम करता है। –

+0

इस प्रश्न में एक बहु-वर्ण स्ट्रिंग (जो आपने अपेक्षा की थी) के आधार पर एक स्ट्रिंग को विभाजित करने के कुछ सुझाव दिए हैं, लेकिन उनमें से अधिकांश स्ट्रिंग सूचियों के साथ काम करते हैं, सरणी नहीं: http://stackoverflow.com/questions/15424293/how-to-split-string-by-a-multi-character-delimiter – quasoft

उत्तर

15

यह फ़ंक्शन लगातार विभाजक को मर्ज करने के लिए डिज़ाइन नहीं किया गया है।

foo,,bar 

क्या आप SplitString('foo,,bar', ',') उम्मीद करेंगे वापस जाने के लिए: उदाहरण के लिए, अल्पविराम पर निम्न स्ट्रिंग बंटवारे पर विचार? क्या आप ('foo', 'bar') देख रहे हैं या उत्तर ('foo', '', 'bar') होना चाहिए? यह एक प्राथमिकता स्पष्ट नहीं है जो सही है, और अलग-अलग उपयोग के मामले अलग-अलग आउटपुट चाहते हैं।

यदि आपका मामला है, तो आपने दो डिलीमीटर, ';' और ' ' निर्दिष्ट किए हैं। इसका मतलब है कि ';' पर और फिर से ' ' पर

'a'; 'b' 

विभाजन। उन दो डिलीमीटरों के बीच कुछ भी नहीं है, और इसलिए 'a' और 'b' के बीच एक खाली स्ट्रिंग लौटा दी गई है।

से विधि XE3 में पेश की गई TStringSplitOptions पैरामीटर है। यदि आप उस पैरामीटर के लिए ExcludeEmpty पास करते हैं तो लगातार विभाजक को एकल विभाजक के रूप में माना जाता है। इस कार्यक्रम:

{$APPTYPE CONSOLE} 

uses 
    System.SysUtils; 

var 
    S: string; 

begin 
    for S in '''a''; ''b''; ''c'''.Split([';', ' '], ExcludeEmpty) do begin 
    Writeln(S); 
    end; 
end. 

आउटपुट:

 
'a' 
'b' 
'c' 

लेकिन अब मुझे लगता है कि आप अपने खुद के विभाजन समारोह रोल करने के लिए जा रहे हैं तो आप इस XE2 में आप के लिए उपलब्ध नहीं है। जो इस तरह दिख सकता है:

function IsSeparator(const C: Char; const Separators: string): Boolean; 
var 
    sep: Char; 
begin 
    for sep in Separators do begin 
    if sep=C then begin 
     Result := True; 
     exit; 
    end; 
    end; 
    Result := False; 
end; 

function Split(const Str, Separators: string): TArray<string>; 
var 
    CharIndex, ItemIndex: Integer; 
    len: Integer; 
    SeparatorCount: Integer; 
    Start: Integer; 
begin 
    len := Length(Str); 
    if len=0 then begin 
    Result := nil; 
    exit; 
    end; 

    SeparatorCount := 0; 
    for CharIndex := 1 to len do begin 
    if IsSeparator(Str[CharIndex], Separators) then begin 
     inc(SeparatorCount); 
    end; 
    end; 

    SetLength(Result, SeparatorCount+1); // potentially an over-allocation 
    ItemIndex := 0; 
    Start := 1; 
    CharIndex := 1; 
    for CharIndex := 1 to len do begin 
    if IsSeparator(Str[CharIndex], Separators) then begin 
     if CharIndex>Start then begin 
     Result[ItemIndex] := Copy(Str, Start, CharIndex-Start); 
     inc(ItemIndex); 
     end; 
     Start := CharIndex+1; 
    end; 
    end; 

    if len>Start then begin 
    Result[ItemIndex] := Copy(Str, Start, len-Start+1); 
    inc(ItemIndex); 
    end; 

    SetLength(Result, ItemIndex); 
end; 

बेशक, यह सब मानते हैं कि आप एक विभाजक के रूप में कार्य करने के लिए एक जगह चाहते हैं। आपने उस कोड में पूछा है, लेकिन शायद आप वास्तव में एक विभाजक के रूप में कार्य करने के लिए केवल ; चाहते हैं। उस स्थिति में आप शायद ';' को विभाजक के रूप में पास करना चाहते हैं, और लौटाए गए स्ट्रिंग को ट्रिम करें।

+0

इस विस्तृत स्पष्टीकरण के लिए धन्यवाद! –

14

SplitString सोचा होगा कि Delimiters निरूपित एकल सीमांकक बंटवारे स्ट्रिंग के लिए इस्तेमाल किया स्ट्रिंग

function SplitString(const S, Delimiters: string): TStringDynArray; 

वन के रूप में परिभाषित किया गया है, लेकिन यह वास्तव में एक विभाजन स्ट्रिंग के लिए उपयोग किए गए वर्णों का सेट को दर्शाता है। Delimiters स्ट्रिंग में प्रत्येक वर्ण का उपयोग संभावित डिलीमीटरों में से एक के रूप में किया जाएगा।

SplitString

निर्दिष्ट सीमांकक वर्ण द्वारा सीमांकित विभिन्न भागों में एक स्ट्रिंग विभाजन। स्प्लिटस्ट्रिंग अलग-अलग हिस्सों में एक स्ट्रिंग को विभाजित करता है निर्दिष्ट डिलीमीटर वर्ण द्वारा सीमित। एस विभाजन होने की स्ट्रिंग है। Delimiters एक स्ट्रिंग है जिसमें वर्ण डिलीमीटर के रूप में परिभाषित किया गया है।

+1

मुझे लगता है कि वे इसे 'डेलीमीटर' (एकवचन) कहते हैं, न कि 'Delimiters'। एफडब्लूआईडब्लूडब्ल्यू, बाद के संस्करणों में, 'टीस्ट्रिंगहेल्पर' में 'स्प्लिट' का एक संस्करण है जो स्ट्रिंग को डिलीमीटर के रूप में भी लेता है, न केवल वर्ण, बल्कि दुर्भाग्यवश XE2 में नहीं। –

+0

@RudyVelthuis सहमत हैं। लेकिन यदि आप देशी अंग्रेजी स्पीकर नहीं हैं तो डेलीमीटर और डेलिमिटर अर्थों के बीच ठीक रेखा खो सकती है। इसके अलावा, अन्य भाषाओं में विभाजित संचालन आमतौर पर पूर्ण, सटीक डिलीमीटर लेते हैं, इसलिए यह डेल्फी कार्यान्वयन उस पहलू से भी भ्रमित है। –

+0

@ रुडी वेल्थुइट्स, लेकिन स्प्लिट के पास क्विर्क का अपना सेट भी है: http://stackoverflow.com/questions/28410901/string-split-works-strange-when-last-value-is-empty –

5

ऐसा इसलिए है क्योंकि स्प्लिटस्ट्रिंग का दूसरा पैरामीटर एकल वर्ण डिलीमीटर की एक सूची है, इसलिए '; 'का अर्थ है' पर विभाजित ';' या एक '' पर विभाजित। तो स्ट्रिंग प्रत्येक ';' पर विभाजित है और हर जगह, और ';' के बीच और 'कुछ भी नहीं है, इसलिए खाली तार।

संबंधित मुद्दे