arrays - स्विफ्ट में नई लाइनों द्वारा एक स्ट्रिंग को कैसे विभाजित किया जाए



string swift (6)

मेरे पास एक स्ट्रिंग है जो मुझे एक टेक्स्ट फ़ाइल से मिली है।

पाठ फ़ाइल:

Line 1
Line 2
Line 3
...

मैं इसे एक सरणी, प्रति पंक्ति एक सरणी तत्व में बदलना चाहता हूं।

[ "Line 1", "Line 2", "Line 3", ... ]

फ़ाइल को कैसे सहेजा गया था, इसके आधार पर, स्ट्रिंग निम्न में से एक फॉर्म ले सकती है:

  • string = "Line 1\nLine 2\nLine 3\n..." जहां \n नई लाइन (लाइन फीड) वर्ण है

  • string = "Line 1\r\nLine 2\r\nLine 3\r\n..." जहाँ \r गाड़ी वापसी वर्ण है।

जैसा कि मैं समझता हूं, आज Apple / Linux में आमतौर पर \n का उपयोग किया जाता है, जबकि Windows में \r\n का उपयोग किया जाता है।

किसी भी खाली तत्वों के बिना स्ट्रिंग सरणी प्राप्त करने के लिए मैं किसी भी पंक्ति विराम पर एक स्ट्रिंग कैसे विभाजित करूं?

अद्यतन करें

कई समाधान हैं जो नीचे काम करते हैं। इस बिंदु पर मेरे पास किसी को अन्य की तुलना में अधिक सही चुनने के लिए कोई बाध्यकारी कारण नहीं है। पसंद को प्रभावित करने वाले कुछ कारक (1) यह "स्विफ्ट" कैसे हो सकते हैं और (2) यह बहुत लंबे तार के लिए कितना तेज है। आप उनमें से एक या अधिक को अपवित्र करके और / या एक टिप्पणी छोड़ कर प्रतिक्रिया प्रदान कर सकते हैं।

यहाँ मेरा संक्षिप्त जवाब देखें

https://code.i-harness.com


किसी भी खाली तत्वों के बिना स्ट्रिंग सरणी प्राप्त करने के लिए मैं किसी भी पंक्ति विराम पर एक स्ट्रिंग कैसे विभाजित करूं?

आप लगभग वहाँ थे - यह सिर्फ अनुगामी बंद है जो यहाँ अलग है:

let array = stringFromFile.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()).filter{!$0.isEmpty}

जो निम्नानुसार है:

let newLineChars = NSCharacterSet.newlineCharacterSet() // newline characters defined as (U+000A–U+000D, U+0085)
let array = stringFromFile.componentsSeparatedByCharactersInSet(newLineChars).filter{!$0.isEmpty}

ETA: अनुगामी बंद होने पर अनावश्यक अतिरिक्त कोष्ठक हटा दिए गए


यह उत्तर पहले से दिए गए अन्य समाधानों का सारांश है। यह मेरे फुलर उत्तर से आता है, लेकिन यहां उपलब्ध वास्तविक विधि विकल्पों का उपयोग करना उपयोगी होगा।

नई लाइनें आमतौर पर \n वर्ण के साथ बनाई जाती हैं, लेकिन \r\n (विंडोज में सहेजी गई फ़ाइलों से) के साथ भी बनाई जा सकती हैं।

समाधान की

1. componentsSeparatedByCharactersInSet

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lineArray = multiLineString.componentsSeparatedByCharactersInSet(newlineChars).filter{!$0.isEmpty}
// "[Line 1, Line 2, Line 3]"

यदि filter का उपयोग नहीं किया गया था, तो \r\n एक खाली सरणी तत्व का उत्पादन करेगा क्योंकि यह दो वर्णों के रूप में गिना जाता है और इसलिए एक ही स्थान पर दो बार स्ट्रिंग को अलग करता है।

2. split

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lineArray = multiLineString.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init)
// "[Line 1, Line 2, Line 3]"

या

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
let lineArray = multiLineString.characters.split { $0 == "\n" || $0 == "\r\n" }.map(String.init)
// "[Line 1, Line 2, Line 3]"

यहाँ \r\n को एक एकल स्विफ्ट वर्ण (एक विस्तारित ग्रेफ़ेम क्लस्टर) के रूप में गिना जाता है

3. enumerateLines

let multiLineString = "Line 1\nLine 2\r\nLine 3\n"
var lineArray = [String]()
multiLineString.enumerateLines { (line, stop) -> () in
    lineArray.append(line)
}
// "[Line 1, Line 2, Line 3]"

enumerateLine सिंटैक्स के बारे में अधिक जानने के लिए, यह उत्तर भी देखें।

टिप्पणियाँ:

  • एक मल्टी लाइन स्ट्रिंग आमतौर पर दोनों \r\n और \n नहीं \n लेकिन मैं यहां यह दिखाने के लिए कर रहा हूं कि ये विधियां दोनों प्रारूपों को संभाल सकती हैं।
  • NSCharacterSet.newlineCharacterSet() (U + 000A-U + 000D, U + 0085) के रूप में परिभाषित की गई नई वर्ण रेखाएँ हैं, जिनमें \r और \n
  • यह उत्तर मेरे पिछले प्रश्न के उत्तरों का सारांश है। अधिक विस्तार के लिए उन उत्तरों को पढ़ें।

स्विफ्ट 2 में, शीर्ष-स्तरीय split फ़ंक्शन अब CollectionType पर एक विधि है (जो String प्रत्येक "वर्ण दृश्य" के अनुरूप है)। विधि के दो संस्करण हैं, आप चाहते हैं कि एक बंद करने के लिए एक विधेय के रूप में संकेत मिलता है कि क्या किसी दिए गए तत्व को एक विभाजक के रूप में माना जाना चाहिए।

आप स्ट्रिंग से चरित्र संग्रह को UTF16 वर्णों के संग्रह के रूप में string.utf16 का उपयोग करके string.utf16 कर string.utf16 , जिससे उन्हें NSCharacterSet API के साथ संगत किया जा सकता है। इस तरह, हम आसानी से क्लोजर के अंदर देख सकते हैं कि क्या स्ट्रिंग में दिया गया कोई कैरेक्टर न्यूलाइन कैरेक्टर सेट का सदस्य है।

यह ध्यान देने योग्य है कि split(_:) वर्णों की एक SubSequence (मूल रूप से एक Slice ) SubSequence , इसलिए इसे वापस स्ट्रिंग्स की एक सरणी में बदलने की आवश्यकता है जो आमतौर पर अधिक उपयोगी होती है। मैंने इसे नीचे दिए गए flatMap(String.init) का उपयोग करते हुए किया है - String पर UTF16View इनिशियलाइज़र उपलब्ध नहीं है, इसलिए flatMap का उपयोग किसी भी nil मान को अनदेखा कर देगा, जो आपको वापस आ सकता है, यह सुनिश्चित करता है कि आपको गैर-वैकल्पिक स्ट्रिंग्स का एक सरणी वापस मिल जाए।

तो ऐसा करने के लिए एक अच्छी स्विफ्ट की तरह:

let str = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lines = str.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init)
// lines = ["Line 1", "Line 2", "Line 3"]

यह अच्छा बनाता है कि split विधि में एक पैरामीटर allowEmptySubsequences , जो यह सुनिश्चित करता है कि आपको परिणाम में कोई खाली वर्ण अनुक्रम प्राप्त नहीं होता है। यह डिफ़ॉल्ट रूप से false है, इसलिए आपको वास्तव में इसे निर्दिष्ट करने की आवश्यकता नहीं है।

संपादित करें

यदि आप NSCharacterSet पूरी तरह बचना चाहते हैं, तो आप यूनिकोड के अनुरूप Character के संग्रह को आसानी से विभाजित कर सकते हैं।

let lines = str.characters.split { $0 == "\n" || $0 == "\r\n" }.map(String.init)

स्विफ्ट "\r\n" को एकल विस्तारित अंगूर के समूह के रूप में व्यवहार करने में सक्षम है, इसे String बनाने के बजाय तुलना के लिए एकल Character रूप में उपयोग कर रहा है। यह भी ध्यान दें कि किसी Character से स्ट्रिंग बनाने का इनिशियल नॉन फेक है, इसलिए हम सिर्फ map उपयोग कर सकते हैं।


Xcode 8.2 में, स्विफ्ट 3.0.1:

NSString विधि घटकों का उपयोग करें (अलग-अलग :)

let text = "line1\nline2"
let array = text.components(separatedBy: CharacterSet.newlines)

या स्ट्रिंग विधि enumerateLines का उपयोग करें, जैसे Leo Dabus का जवाब


स्विफ्ट 5 या बाद में

नई Character गुण का उपयोग करके आप अपने String को विभाजित कर सकते हैं।

let sentence = "Line 1\nLine 2\nLine 3\n"
var lines = sentence.split { $0.isNewline }
print(lines)   // "[Line 1, Line 2, Line 3]"

मूल उत्तर

आप स्ट्रिंग विधि enumerateLines का उपयोग कर सकते हैं:

एक स्ट्रिंग में सभी लाइनों की गणना करता है।

स्विफ्ट 3 या बाद में

let sentence = "Line 1\nLine 2\nLine 3\n"
var lines: [String] = []
sentence.enumerateLines { line, _ in
    lines.append(line)
}
print(lines)   // "[Line 1, Line 2, Line 3]"
extension String {
    var lines: [String] {
        var result: [String] = []
        enumerateLines { line, _ in result.append(line) }
        return result
    }
}

उपयोग:

let sentence2 = "Line 4\nLine 5\nLine 6\n"
let sentence2Lines = sentence2.lines

print(sentence2Lines)    // ["Line 4", "Line 5", "Line 6"]


let sentence3 = "Line 7\r\nLine 8\r\nLine 9\r\n"
let sentence3Lines = sentence3.lines

print(sentence3Lines)  // "[Line 7, Line 8, Line 9]"

let test1 = "Line1\n\rLine2\nLine3\rLine4"
let t1 = test1.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
let t2 = t1.filter{ $0 != "" }
let t3 = t1.filter{ !$0.isEmpty }





newline