ios - स्विफ्ट: एक स्ट्रिंग को एक सरणी में विभाजित करें




string swift (18)

व्हाइटस्पेस मुद्दा

आम तौर पर, लोग इस समस्या और खराब समाधानों को फिर से शुरू करते हैं। क्या यह एक जगह है? "" और "\ n", "\ t" या कुछ यूनिकोड व्हाइटस्पेस कैरेक्टर जो आपने कभी नहीं देखा है, किसी भी छोटे हिस्से में नहीं है क्योंकि यह अदृश्य है। जबकि आप दूर हो सकते हैं

एक कमजोर समाधान

import Foundation
let pieces = "Mary had little lamb".componentsSeparatedByString(" ")

यदि आपको कभी भी वास्तविकता पर अपनी पकड़ को हिलाकर रखने की ज़रूरत है तो तारों या तिथियों पर एक डब्ल्यूडब्ल्यूडीसी वीडियो देखें। संक्षेप में, ऐप्पल को इस तरह के सांसारिक कार्य को हल करने की अनुमति देने के लिए लगभग हमेशा बेहतर होता है।

मजबूत समाधान: NSCharacterSet का उपयोग करें

इसे सही तरीके से करने का तरीका, आईएमएचओ, NSCharacterSet का उपयोग NSCharacterSet क्योंकि जैसा कि पहले बताया गया था कि आपका व्हाइटस्पेस आपके द्वारा अपेक्षित नहीं हो सकता है और ऐप्पल ने एक व्हाइटस्पेस चरित्र सेट प्रदान किया है। विभिन्न प्रदान किए गए चरित्र सेटों का पता लगाने के लिए ऐप्पल के एनएससीएचएआरएटरसेट डेवलपर दस्तावेज़ों को जांचें और फिर, केवल तभी, एक नया चरित्र सेट बढ़ाएं या बनाएं यदि यह आपकी आवश्यकताओं के अनुरूप नहीं है।

NSCharacterSet व्हाइटस्पेस सेट करें

यूनिकोड जनरल श्रेणी जेड और वर्णक तालिका (यू + 000 9) में वर्णों वाला एक वर्ण सेट देता है।

let longerString: String = "This is a test of the character set splitting system"
let components = longerString.components(separatedBy: .whitespaces)
print(components)

कहो मेरे पास एक स्ट्रिंग है:

var fullName: String = "First Last"

मैं सफेद स्थान पर स्ट्रिंग बेस को विभाजित करना चाहता हूं और मानों को उनके संबंधित चरों में असाइन करना चाहता हूं

var fullNameArr = // something like: fullName.explode(" ") 

var firstName: String = fullNameArr[0]
var lastName: String? = fullnameArr[1]

साथ ही, कभी-कभी उपयोगकर्ताओं का अंतिम नाम नहीं हो सकता है।


WMios के उत्तर के विकल्प के रूप में, आप componentsSeparatedByCharactersInSet SeparatedByCharactersInSet का भी उपयोग कर सकते हैं, जो आपके पास अधिक विभाजक (खाली स्थान, अल्पविराम, आदि) के मामले में आसान हो सकता है।

आपके विशिष्ट इनपुट के साथ:

let separators = NSCharacterSet(charactersInString: " ")
var fullName: String = "First Last";
var words = fullName.componentsSeparatedByCharactersInSet(separators)

// words contains ["First", "Last"]

एकाधिक विभाजक का उपयोग करना:

let separators = NSCharacterSet(charactersInString: " ,")
var fullName: String = "Last, First Middle";
var words = fullName.componentsSeparatedByCharactersInSet(separators)

// words contains ["Last", "First", "Middle"]

इनमें से अधिकतर उत्तरों का मानना ​​है कि इनपुट में एक जगह है - सफेद जगह नहीं, और उस पर एक ही स्थान। यदि आप सुरक्षित रूप से उस धारणा को सुरक्षित कर सकते हैं, तो स्वीकार किए गए उत्तर (बेनेट से) काफी सुरुचिपूर्ण है और जिस तरीके से मैं कर सकता हूं, उसके साथ मैं भी जा रहा हूं।

जब हम उस धारणा को नहीं बना सकते हैं, तो एक और मजबूत समाधान को निम्नलिखित सीटेशंस को कवर करने की आवश्यकता होती है, जिन पर अधिकतर उत्तर इस पर विचार नहीं करते हैं:

  • आवर्ती पात्रों सहित टैब / न्यूलाइन / रिक्त स्थान (व्हाइटस्पेस)
  • अग्रणी / पिछला सफेद स्थान
  • ऐप्पल / लिनक्स ( \n ) और विंडोज़ ( \r\n ) न्यूलाइन अक्षर

इन मामलों को कवर करने के लिए यह समाधान सभी जगहों (पुनरावर्ती और विंडोज़ न्यूलाइन अक्षरों सहित) को एक ही स्थान, trims में बदलने के लिए regex का उपयोग करता है, फिर एक ही स्थान से विभाजित होता है:

स्विफ्ट 3:

let searchInput = "  First \r\n \n \t\t\tMiddle    Last "
let searchTerms = searchInput 
    .replacingOccurrences(
        of: "\\s+",
        with: " ",
        options: .regularExpression
    )
    .trimmingCharacters(in: .whitespaces)
    .components(separatedBy: " ")

// searchTerms == ["First", "Middle", "Last"]

उम्मीद है कि यह सहायक है

स्विफ्ट 4: एक स्ट्रिंग को एक सरणी में विभाजित करें। चरण 1: स्ट्रिंग असाइन करें। चरण 2: @ विभाजन पर आधारित है। नोट: variableName.components (अलग से: "विभाजित कीवर्ड")

let fullName: String = "First Last @ triggerd event of the session by session storage @ it can be divided by the event of the trigger."
let fullNameArr = fullName.components(separatedBy: "@")
print("split", fullNameArr)

मुझे एक दिलचस्प मामला मिला, वह

विधि 1

var data:[String] = split( featureData ) { $0 == "\u{003B}" }

जब मैंने सर्वर से लोड किए गए डेटा से कुछ प्रतीक विभाजित करने के लिए इस कमांड का उपयोग किया, तो यह सिम्युलेटर में परीक्षण करते समय विभाजित हो सकता है और परीक्षण डिवाइस के साथ सिंक हो सकता है, लेकिन यह प्रकाशित ऐप में विभाजित नहीं होगा, और विज्ञापन हॉक

मुझे इस त्रुटि को ट्रैक करने में बहुत समय लगता है, यह कुछ स्विफ्ट संस्करण, या कुछ आईओएस संस्करण या न तो शापित हो सकता है

यह HTML कोड के बारे में भी नहीं है, क्योंकि मैं stringRyRemovingPercentEncoding स्ट्रिंग करने का प्रयास करता हूं और यह अभी भी काम नहीं कर रहा है

अतिरिक्त 10/10/2015

स्विफ्ट 2.0 में इस विधि को बदल दिया गया है

var data:[String] = featureData.split {$0 == "\u{003B}"}

विधि 2

var data:[String] = featureData.componentsSeparatedByString("\u{003B}")

जब मैंने इस कमांड का उपयोग किया, तो यह उसी डेटा को विभाजित कर सकता है जो सर्वर से सही तरीके से लोड होता है

निष्कर्ष, मैं वास्तव में विधि 2 का उपयोग करने का सुझाव देता हूं

string.componentsSeparatedByString("")

मुझे समाधान नहीं मिला है जो 3 या अधिक घटकों वाले नामों को संभालेगा और पुराने आईओएस संस्करणों का समर्थन करेगा।

struct NameComponentsSplitter {

    static func split(fullName: String) -> (String?, String?) {
        guard !fullName.isEmpty else {
            return (nil, nil)
        }
        let components = fullName.components(separatedBy: .whitespacesAndNewlines)
        let lastName = components.last
        let firstName = components.dropLast().joined(separator: " ")
        return (firstName.isEmpty ? nil : firstName, lastName)
    }
}

उत्तीर्ण परीक्षण के मामले:

func testThatItHandlesTwoComponents() {
    let (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Smith")
    XCTAssertEqual(firstName, "John")
    XCTAssertEqual(lastName, "Smith")
}

func testThatItHandlesMoreThanTwoComponents() {
    var (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Clark Smith")
    XCTAssertEqual(firstName, "John Clark")
    XCTAssertEqual(lastName, "Smith")

    (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Clark Jr. Smith")
    XCTAssertEqual(firstName, "John Clark Jr.")
    XCTAssertEqual(lastName, "Smith")
}

func testThatItHandlesEmptyInput() {
    let (firstName, lastName) = NameComponentsSplitter.split(fullName: "")
    XCTAssertEqual(firstName, nil)
    XCTAssertEqual(lastName, nil)
}

यह बीटा 5 में फिर से बदल गया है। वी! यह अब संग्रह प्रकार पर एक तरीका है

पुराना:

var fullName = "First Last"
var fullNameArr = split(fullName) {$0 == " "}

नया:

var fullName = "First Last"
var fullNameArr = fullName.split {$0 == " "}

सेब रिलीज नोट्स


यहां एक एल्गोरिदम है जो मैं अभी बनाता हूं, जो सरणी से किसी भी Character द्वारा एक String को विभाजित करेगा और यदि विभाजित वर्णों के साथ सबस्ट्रिंग को रखने की कोई इच्छा है तो कोई swallow पैरामीटर को true सेट कर सकता true

एक्सकोड 7.3 - स्विफ्ट 2.2:

extension String {

    func splitBy(characters: [Character], swallow: Bool = false) -> [String] {

        var substring = ""
        var array = [String]()
        var index = 0

        for character in self.characters {

            if let lastCharacter = substring.characters.last {

                // swallow same characters
                if lastCharacter == character {

                    substring.append(character)

                } else {

                    var shouldSplit = false

                    // check if we need to split already
                    for splitCharacter in characters {
                        // slit if the last character is from split characters or the current one
                        if character == splitCharacter || lastCharacter == splitCharacter {

                            shouldSplit = true
                            break
                        }
                    }

                    if shouldSplit {

                        array.append(substring)
                        substring = String(character)

                    } else /* swallow characters that do not equal any of the split characters */ {

                        substring.append(character)
                    }
                }
            } else /* should be the first iteration */ {

                substring.append(character)
            }

            index += 1

            // add last substring to the array
            if index == self.characters.count {

                array.append(substring)
            }
        }

        return array.filter {

            if swallow {

                return true

            } else {

                for splitCharacter in characters {

                    if $0.characters.contains(splitCharacter) {

                        return false
                    }
                }
                return true
            }
        }
    }
}

उदाहरण:

"test text".splitBy([" "]) // ["test", "text"]
"test++text--".splitBy(["+", "-"], swallow: true) // ["test", "++" "text", "--"]

स्ट्रिंग हैंडलिंग अभी भी स्विफ्ट में एक चुनौती है और यह महत्वपूर्ण रूप से बदलती रहती है, क्योंकि आप अन्य उत्तरों से देख सकते हैं। उम्मीद है कि चीजें बसने लगती हैं और यह आसान हो जाती है। स्विफ्ट के वर्तमान 3.0 संस्करण के साथ कई विभाजक पात्रों के साथ ऐसा करने का यह तरीका है।

स्विफ्ट 3:

let chars = CharacterSet(charactersIn: ".,; -")
let split = phrase.components(separatedBy: chars)

// Or if the enums do what you want, these are preferred. 
let chars2 = CharacterSet.alphaNumerics // .whitespaces, .punctuation, .capitalizedLetters etc
let split2 = phrase.components(separatedBy: chars2)

स्विफ्ट 2 के लिए, एक्सकोड 7.1:

let complete_string:String = "Hello world"
let string_arr =  complete_string.characters.split {$0 == " "}.map(String.init)
let hello:String = string_arr[0]
let world:String = string_arr[1]

स्विफ्ट तरीका वैश्विक split फ़ंक्शन का उपयोग करना है, जैसे:

var fullName = "First Last"
var fullNameArr = split(fullName) {$0 == " "}
var firstName: String = fullNameArr[0]
var lastName: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil

स्विफ्ट 2 के साथ

स्विफ्ट 2 में आंतरिक वर्ण दृश्य प्रकार के परिचय के कारण विभाजन का उपयोग थोड़ा अधिक जटिल हो जाता है। इसका मतलब है कि स्ट्रिंग अब अनुक्रम प्रकार या कलेक्शन टाइप प्रोटोकॉल को गोद लेती है और आपको स्ट्रिंग इंस्टेंस के कैरेक्टर .characters प्रकार के प्रतिनिधित्व तक पहुंचने के लिए .characters प्रॉपर्टी का उपयोग करना होगा। (नोट: कैरेक्टर व्यू अनुक्रम प्रकार और संग्रह प्रकार प्रोटोकॉल को गोद लेता है)।

let fullName = "First Last"
let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init)
// or simply:
// let fullNameArr = fullName.characters.split{" "}.map(String.init)

fullNameArr[0] // First
fullNameArr[1] // Last 

ऐसा करने का सबसे आसान तरीका घटकों का उपयोग करके हैपरेटेडबी:

स्विफ्ट 2 के लिए:

import Foundation
let fullName : String = "First Last";
let fullNameArr : [String] = fullName.componentsSeparatedByString(" ")

// And then to access the individual words:

var firstName : String = fullNameArr[0]
var lastName : String = fullNameArr[1]

स्विफ्ट 3 के लिए:

import Foundation

let fullName : String = "First Last"
let fullNameArr : [String] = fullName.components(separatedBy: " ")

// And then to access the individual words:

var firstName : String = fullNameArr[0]
var lastName : String = fullNameArr[1]

एक्सकोड 9 स्विफ्ट 4 या एक्सकोड 8.2.1 • स्विफ्ट 3.0.2

यदि आपको किसी व्यक्ति के नाम को उचित रूप से प्रारूपित करने की आवश्यकता है, तो आप PersonNameComponentsFormatter उपयोग कर सकते हैं।

PersonNameComponentsFormatter क्लास किसी व्यक्ति के नाम के घटकों के स्थानीय प्रतिनिधित्व प्रदान करता है, जैसा कि एक PersonNameComponents ऑब्जेक्ट द्वारा दर्शाया गया है। उपयोगकर्ता को व्यक्ति नाम जानकारी प्रदर्शित करते समय स्थानीय नाम बनाने के लिए इस कक्षा का उपयोग करें।

// iOS (9.0 and later), macOS (10.11 and later), tvOS (9.0 and later), watchOS (2.0 and later)
let nameFormatter = PersonNameComponentsFormatter()

let name =  "Mr. Steven Paul Jobs Jr."
// personNameComponents requires iOS (10.0 and later)
if let nameComps  = nameFormatter.personNameComponents(from: name) {
    nameComps.givenName    // Steven
    nameComps.middleName   // Paul
    nameComps.familyName   // Jobs
    nameComps.nameSuffix   // Jr.
    nameComps.namePrefix   // Mr.

    // It can also be convufgured to format your names
    // Default (same as medium), short, long or abbreviated

    nameFormatter.style = .default
    nameFormatter.string(from: nameComps)   // "Steven Jobs"

    nameFormatter.style = .short
    nameFormatter.string(from: nameComps)   // "Steven"

    nameFormatter.style = .long
    nameFormatter.string(from: nameComps)   // "Mr. Steven Paul Jobs jr."

    nameFormatter.style = .abbreviated
    nameFormatter.string(from: nameComps)   // SJ

    // It can also be use to return an attributed string using annotatedString method
    nameFormatter.style = .long
    nameFormatter.annotatedString(from: nameComps)   // "Mr. Steven Paul Jobs jr."
}


स्विफ्ट 2.2 के अनुसार

आप बस 2 लाइन कोड लिखते हैं और आपको स्प्लिट स्ट्रिंग मिल जाएगी।

let fullName = "FirstName LastName"
var splitedFullName = fullName.componentsSeparatedByString(" ")
print(splitedFullName[0])
print(splitedFullName[1]) 

का आनंद लें। :)


स्विफ्ट 3

let line = "AAA    BBB\t CCC"
let fields = line.components(separatedBy: .whitespaces).filter {!$0.isEmpty}
  • AAA , BBB और CCC तीन स्ट्रिंग देता है
  • खाली फ़ील्ड बाहर फ़िल्टर
  • एकाधिक रिक्त स्थान और सारणीकरण वर्णों को संभालता है
  • यदि आप नई लाइनों को संभालना चाहते हैं, तो .whitespaces और .whitespacesAndNewlines साथ .whitespacesAndNewlines को .whitespacesAndNewlines

स्विफ्ट 4

let words = "these words will be elements in an array".components(separatedBy: " ")

let str = "one two"
let strSplit = str.characters.split(" ").map(String.init) // returns ["one", "two"]

एक्सकोड 7.2 (7 सी 68)


var fullName = "James Keagan Michael"
let first = fullName.components(separatedBy: " ").first?.isEmpty == false ? fullName.components(separatedBy: " ").first! : "John"
let last =  fullName.components(separatedBy: " ").last?.isEmpty == false && fullName.components(separatedBy: " ").last != fullName.components(separatedBy: " ").first ? fullName.components(separatedBy: " ").last! : "Doe"
  • पहले और अंतिम नाम को अस्वीकार करें
  • यदि कोई पूर्ण नाम अमान्य है, तो प्लेसहोल्डर मान "जॉन डो" लें




split