स्विफ्ट प्रोग्रामिंग भाषा में एक स्ट्रिंग का nth चरित्र प्राप्त करें


419

मैं एक स्ट्रिंग का nth चरित्र कैसे प्राप्त कर सकता हूं? मैंने []बिना किसी भाग्य के ब्रैकेट ( ) एक्सेसर की कोशिश की ।

var string = "Hello, world!"

var firstChar = string[0] // Throws error

त्रुटि: 'सबस्क्रिप्ट' अनुपलब्ध है: स्ट्रिंग को एक इंट के साथ सब्मिट नहीं किया जा सकता है, चर्चा के लिए दस्तावेज़ीकरण टिप्पणी देखें


1
त्रुटि संदेश "एक इंट के साथ स्ट्रिंग को कम नहीं कर सकता, चर्चा के लिए प्रलेखन टिप्पणी देखें"
andrewn

var firstChar = string.index(string.startIndex, offsetBy: 0)इसके बजाय उपयोग करें
Sazzad Hissain Khan

@SazzadHissainKhan इसका परिणाम स्ट्रिंग इंडेक्स में होगा, चरित्र नहीं। Btw क्यों नहीं बस string.startIndex? पहले चरित्र के लिए string[string.startIndex] या बस string.first। ध्यान दें कि पहला दृष्टिकोण आपको यह जांचने की आवश्यकता है कि क्या स्ट्रिंग खाली है पहला दूसरा एक वैकल्पिक रिटर्न देता है
लियो डबस

जवाबों:


567

ध्यान दें: कृपया स्विफ्ट 4 और स्विफ्ट 5 के लिए उचित कार्यान्वयन के लिए लियो डबस का उत्तर देखें ।

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

Substringप्रकार स्विफ्ट 4 में पेश किया गया था सबस्ट्रिंग तेजी से और अधिक कुशल मूल तार के साथ भंडारण साझा करके बनाने के लिए है, ताकि क्या सबस्क्रिप्ट कार्यों लौटना चाहिए।

इसे यहाँ आज़माएँ

extension StringProtocol {
    subscript(offset: Int) -> Character { self[index(startIndex, offsetBy: offset)] }
    subscript(range: Range<Int>) -> SubSequence {
        let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
        return self[startIndex..<index(startIndex, offsetBy: range.count)]
    }
    subscript(range: ClosedRange<Int>) -> SubSequence {
        let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
        return self[startIndex..<index(startIndex, offsetBy: range.count)]
    }
    subscript(range: PartialRangeFrom<Int>) -> SubSequence { self[index(startIndex, offsetBy: range.lowerBound)...] }
    subscript(range: PartialRangeThrough<Int>) -> SubSequence { self[...index(startIndex, offsetBy: range.upperBound)] }
    subscript(range: PartialRangeUpTo<Int>) -> SubSequence { self[..<index(startIndex, offsetBy: range.upperBound)] }
}

को Substringए में परिवर्तित करने के लिए String, आप बस कर सकते हैं String(string[0..2]), लेकिन आपको केवल यही करना चाहिए कि यदि आप सबस्ट्रिंग को रखने की योजना बनाते हैं। अन्यथा, इसे रखना अधिक कुशल है Substring

यह बहुत अच्छा होगा यदि कोई व्यक्ति इन दोनों एक्सटेंशन को एक में विलय करने का अच्छा तरीका समझ सकता है। मैंने StringProtocol सफलता के बिना विस्तार करने की कोशिश की , क्योंकि indexविधि वहां मौजूद नहीं है। नोट: यह उत्तर पहले ही संपादित किया जा चुका है, इसे ठीक से लागू किया गया है और अब यह सबस्ट्रिंग के लिए भी काम करता है। अपने स्ट्रिंगप्रोटोकॉल प्रकार की सदस्यता लेते समय दुर्घटना से बचने के लिए बस एक वैध सीमा का उपयोग करना सुनिश्चित करें। एक सीमा के साथ सबस्क्रिप्टिंग के लिए जो सीमा मानों के साथ दुर्घटनाग्रस्त नहीं होगी, आप इस कार्यान्वयन का उपयोग कर सकते हैं


यह बिल्ट-इन क्यों नहीं है?

त्रुटि संदेश कहता है "चर्चा के लिए प्रलेखन टिप्पणी देखें" । एप्पल फ़ाइल में निम्न विवरण प्रदान UnavailableStringAPIs.swift :

पूर्णांक के साथ तार उपलब्ध नहीं है।

" iएक स्ट्रिंग में वें चरित्र " की अवधारणा के विभिन्न पुस्तकालयों और सिस्टम घटकों में अलग-अलग व्याख्याएं हैं। उपयोग की स्थिति और इसमें शामिल एपीआई के अनुसार सही व्याख्या का चयन किया जाना चाहिए, इसलिए String पूर्णांक के साथ सब्सक्राइब नहीं किया जा सकता है।

स्विफ्ट स्ट्रिंग्स के अंदर संग्रहीत चरित्र डेटा तक पहुंचने के कई अलग-अलग तरीके प्रदान करता है।

  • String.utf8स्ट्रिंग में UTF-8 कोड इकाइयों का एक संग्रह है। स्ट्रिंग को UTF-8 में परिवर्तित करते समय इस API का उपयोग करें। अधिकांश POSIX APIs UTF-8 कोड इकाइयों के संदर्भ में प्रक्रिया करते हैं।

  • String.utf16स्ट्रिंग में UTF-16 कोड इकाइयों का एक संग्रह है। अधिकांश कोको और कोको टच एपीआई यूटीएफ -16 कोड इकाइयों के संदर्भ में स्ट्रिंग की प्रक्रिया करते हैं। उदाहरण के लिए, यूटीएफ -16 कोड इकाइयों के संदर्भ में ऑफसेट और लंबाई के NSRangeसाथ उपयोग किए जाने वाले स्टोर NSAttributedStringऔर इंस्टेंसेस के उदाहरण NSRegularExpression

  • String.unicodeScalarsयूनिकोड स्केलर्स का एक संग्रह है। जब आप वर्ण डेटा के निम्न-स्तरीय हेरफेर कर रहे हों, तो इस API का उपयोग करें।

  • String.characters विस्तारित ग्रैफेम क्लस्टर का एक संग्रह है, जो उपयोगकर्ता-कथित पात्रों का एक अनुमान है।

ध्यान दें कि जब प्रसंस्करण स्ट्रिंग जिसमें मानव-पठनीय पाठ होता है, तो चरित्र-दर-चरित्र प्रसंस्करण को संभव सबसे बड़ी सीमा तक बचा जाना चाहिए। उच्च स्तरीय उपयोग स्थल के प्रति संवेदनशील यूनिकोड एल्गोरिदम के बजाय, उदाहरण के लिए, String.localizedStandardCompare(), String.localizedLowercaseString, String.localizedStandardRangeOfString()आदि


4
Cannot find an overload for 'advance' that accepts an argument list of type '(String.Index, T)'... String.Indexऔर Intसंगत नहीं हैं।

7
यदि आप Cannot subscript a value of type 'String'...इस उत्तर को देखते हैं : stackoverflow.com/a/31265316/649379
SoftDesigner

24
जब मैं इसका उपयोग करने की कोशिश करता हूं, तो मुझे मिलता है Ambiguous use of 'subscript'
jowie

18
चेतावनी! नीचे दिया गया विस्तार बहुत ही अयोग्य है। हर बार स्ट्रिंग को पूर्णांक के साथ एक्सेस किया जाता है, इसके आरंभिक सूचकांक को आगे बढ़ाने के लिए O (n) फ़ंक्शन होता है। लीनियर लूप को दूसरे लीनियर लूप के अंदर चलाने का मतलब है कि यह लूप गलती से O (n2) है - जैसे-जैसे स्ट्रिंग की लंबाई बढ़ती जाती है, यह लूप क्वाड्रेटिक रूप से बढ़ता जाता है। ऐसा करने के बजाय आप पात्रों के स्ट्रिंग संग्रह का उपयोग कर सकते हैं।
इग्नासियुगोग

2
fatal error: Can't form a Character from an empty String
डेविन बी

341

स्विफ्ट 5.2

let str = "abcdef"
str[1 ..< 3] // returns "bc"
str[5] // returns "f"
str[80] // returns ""
str.substring(fromIndex: 3) // returns "def"
str.substring(toIndex: str.length - 2) // returns "abcd"

आपको इस स्ट्रिंग एक्सटेंशन को अपनी परियोजना में जोड़ना होगा (यह पूरी तरह से परीक्षण किया गया है):

extension String {

    var length: Int {
        return count
    }

    subscript (i: Int) -> String {
        return self[i ..< i + 1]
    }

    func substring(fromIndex: Int) -> String {
        return self[min(fromIndex, length) ..< length]
    }

    func substring(toIndex: Int) -> String {
        return self[0 ..< max(0, toIndex)]
    }

    subscript (r: Range<Int>) -> String {
        let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
                                            upper: min(length, max(0, r.upperBound))))
        let start = index(startIndex, offsetBy: range.lowerBound)
        let end = index(start, offsetBy: range.upperBound - range.lowerBound)
        return String(self[start ..< end])
    }
}

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

let str = "Hello, world!"
let index = str.index(str.startIndex, offsetBy: 4)
str[index] // returns Character 'o'

let endIndex = str.index(str.endIndex, offsetBy:-2)
str[index ..< endIndex] // returns String "o, worl"

String(str.suffix(from: index)) // returns String "o, world!"
String(str.prefix(upTo: index)) // returns String "Hell"

परिवर्तन range.upperBound - range.lowerBoundकरने के लिएrange.count
सिंह Dabus

यह मूल प्रश्न का हिस्सा नहीं है, लेकिन ... अच्छा होगा यदि यह समर्थित असाइनमेंट भी। जैसे, s [i] = "a" :)।
क्रिस प्रिंस

2
मेरा मानना ​​है कि स्विफ्ट के साथ 4.2 सब्सक्रिप्शन दोबारा उपलब्ध नहीं हैं। मुझे यह कहते हुए एक त्रुटि मिलती है: 'सबस्क्रिप्ट' अनुपलब्ध है: एक
सबटाइटल को सब्सक्राइब

2
@ क्रिसह्रिसनextension StringProtocol where Self: RangeReplaceableCollection { subscript(offset: Int) -> Element { get { return self[index(startIndex, offsetBy: offset)] } set { let start = index(startIndex, offsetBy: offset) replaceSubrange(start..<index(after: start), with: [newValue]) } } }
लियो डबस

यह अंतर्निहित कार्य होना चाहिए
अम्मार मुजीब

150

मैं अभी इस स्वच्छंद समाधान के साथ आया था

var firstChar = Array(string)[0]

2
यह (आम) मामले के लिए एक अच्छा त्वरित काम है, जहाँ आप जानते हैं कि आपके पास UTF8 या ASCII एन्कोडेड स्ट्रिंग्स हैं। बस यह सुनिश्चित करें कि तार कभी भी एक एन्कोडिंग में नहीं होंगे जो एक से अधिक बाइट का उपयोग करता है।
जेफ हेय

47
यह बेहद अक्षम लगता है क्योंकि आप पहले अक्षर को प्राप्त करने के लिए पूरे स्ट्रिंग की नकल कर रहे हैं। स्ट्रिंग [स्ट्रिंग का उपयोग करें। startIndex] के बजाय 0 के रूप में सुल्तान ने बताया।
ब्योर्न

6
स्ट्रिंग स्ट्रिंग: var firstChar = Array(string!)[0]अन्यथा यह कहेंगेadd arrayLiteral
मोहम्मद जैद पठान

2
मुझे विश्वास नहीं है कि यह साफ है, तथ्य की बात है कि यह एक दौर है। मुझे पूरा यकीन नहीं है कि ऐरे में कौन सा इनिशियलाइज़र इस्तेमाल किया जाता है, जिससे पहले ऐसा होता है (और मैं यह मान रहा हूँ कि यह सीक्वेंसटेप इनिशियलाइज़र है, जिससे यह ऐरे के लिए अलग-अलग घटकों के रूप में स्ट्रिंग के पात्रों को इकट्ठा करने के लिए होता है)। यह बिल्कुल स्पष्ट नहीं है और भविष्य में टाइपिंग के बिना इसे ठीक किया जा सकता है। यह भी काम नहीं करता है, यदि आप [स्ट्रिंग] .first के माध्यम से सरणी के लिए शॉर्टहैंड का उपयोग करते हैं। @ सुल्तान का समाधान सूचकांक मूल्यों में पके हुए का उपयोग करने के लिए सबसे अच्छा काम करता है। यहाँ क्या हो रहा है, यह कहीं अधिक स्पष्ट है।
कोडिंगआर्ट

2
वाह, संकलक खंड दोष!
फ्रैंक

124

पूर्णांक का उपयोग करते हुए कोई अनुक्रमण नहीं, केवल उपयोग करना String.Index। ज्यादातर रैखिक जटिलता के साथ। आप String.Indexइनका उपयोग करके सबस्ट्रिंग भी बना सकते हैं और सब्सट्रिंग प्राप्त कर सकते हैं।

स्विफ्ट 3.0

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.index(before: someString.endIndex)]
let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)]

let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10)
let substring = someString[range]

स्विफ्ट 2.x

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.endIndex.predecessor()]
let charAtIndex = someString[someString.startIndex.advanceBy(10)]

let range = someString.startIndex..<someString.startIndex.advanceBy(10)
let subtring = someString[range]

ध्यान दें कि आप कभी भी एक स्ट्रिंग से दूसरे स्ट्रिंग में बनाए गए इंडेक्स (या रेंज) का उपयोग नहीं कर सकते हैं

let index10 = someString.startIndex.advanceBy(10)

//will compile
//sometimes it will work but sometimes it will crash or result in undefined behaviour
let charFromAnotherString = anotherString[index10]

7
Stringसूचकांक एक स्ट्रिंग के लिए अद्वितीय हैं। ऐसा इसलिए है क्योंकि अलग-अलग तारों में अलग-अलग मल्टी-यूनिट UTF-16 Charactersऔर / या विभिन्न पदों पर हो सकते हैं इसलिए UTF-16 यूनिट इंडेक्स का मिलान नहीं होगा, एक बहु-यूनिट UTF-16 के अंदर अंत या बिंदु से परे हो सकता है Character
zaph

@Zaph यह स्पष्ट है।
सुल्तान

3
यह बताते हुए कि आप क्यों कहते हैं: "कभी-कभी यह दुर्घटनाग्रस्त हो जाएगा या अपरिभाषित व्यवहार का परिणाम होगा"। शायद यह कहने के लिए बेहतर है कि ऐसा न करें क्योंकि ...
zaf

1
@ सुल्तान ..अब ..<(अपने असाइनमेंट में range) हैं
एरॉन ब्रेजर

3
@CajunLuke मुझे पता है कि इस टिप्पणी को पोस्ट करने में आपको थोड़ी देर हो गई है, लेकिन इस उत्तर पर एक नज़र डालें । आप उपयोग कर सकते हैंvar lastChar = string[string.endIndex.predecessor()]
डेविड एल

122

Xcode 11 • स्विफ्ट 5.1

सब्सट्रेट के लिए सबस्क्रिप्ट भी उपलब्ध कराने के लिए आप स्ट्रिंगप्रोटोकॉल का विस्तार कर सकते हैं:

extension StringProtocol {
    subscript(_ offset: Int)                     -> Element     { self[index(startIndex, offsetBy: offset)] }
    subscript(_ range: Range<Int>)               -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
    subscript(_ range: ClosedRange<Int>)         -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
    subscript(_ range: PartialRangeThrough<Int>) -> SubSequence { prefix(range.upperBound.advanced(by: 1)) }
    subscript(_ range: PartialRangeUpTo<Int>)    -> SubSequence { prefix(range.upperBound) }
    subscript(_ range: PartialRangeFrom<Int>)    -> SubSequence { suffix(Swift.max(0, count-range.lowerBound)) }
}

extension LosslessStringConvertible {
    var string: String { .init(self) }
}

extension BidirectionalCollection {
    subscript(safe offset: Int) -> Element? {
        guard !isEmpty, let i = index(startIndex, offsetBy: offset, limitedBy: index(before: endIndex)) else { return nil }
        return self[i]
    }
}

परिक्षण

let test = "Hello USA 🇺🇸!!! Hello Brazil 🇧🇷!!!"
test[safe: 10]   // "🇺🇸"
test[11]   // "!"
test[10...]   // "🇺🇸!!! Hello Brazil 🇧🇷!!!"
test[10..<12]   // "🇺🇸!"
test[10...12]   // "🇺🇸!!"
test[...10]   // "Hello USA 🇺🇸"
test[..<10]   // "Hello USA "
test.first   // "H"
test.last    // "!"

// Subscripting the Substring
 test[...][...3]  // "Hell"

// Note that they all return a Substring of the original String.
// To create a new String from a substring
test[10...].string  // "🇺🇸!!! Hello Brazil 🇧🇷!!!"

क्या मैं पूछ सकता हूं कि "स्व [सूचकांक (startIndex, ऑफसेटबाय: i)]" क्या है? और "स्व [i]" कैसे काम करता है?
एलनिनली

1
हाय सिंह, समाधान के लिए धन्यवाद! मैं सिर्फ (आज) स्विफ्ट 2.3 से 3 पर स्विच किया गया और आपकी समाधान सबस्क्रिप्ट (रेंज: रेंज <इंट>) त्रुटि "अतिरिक्त तर्क 'सीमित' कॉल में सीमित करता है"। आपको क्या लगता है कि गलत हो सकता है?
अहमत अकोक 14

@ AhmetAkkök क्या आप सुनिश्चित हैं कि आपने कोड नहीं बदला है?
बजे सिंह डबस

1
@ यह पता चला कि मैंने पूरे प्रोजेक्ट को परिवर्तित नहीं किया है, लेकिन ऐप पर एक्सटेंशन नहीं है, मैंने ऐप और एक्सटेंशन दोनों के लिए प्रक्रिया दोहराई और यह अब ठीक काम करता है। आपकी सहायता की बहुत सराहना की गयी!
अहमत अकोक 15

यह बहुत ही जटिल कोड है। return String(Array(characters)[range])स्विफ्ट 3 में करने से क्या फायदा ?
डैन रोसेनस्टार्क

67

स्विफ्ट 4

let str = "My String"

सूचकांक पर स्ट्रिंग

let index = str.index(str.startIndex, offsetBy: 3)
String(str[index])    // "S"

सबस्ट्रिंग

let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)
String(str[startIndex...endIndex])     // "Strin"

पहले एन चार

let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[..<startIndex])    // "My "

अंतिम n वर्ण

let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[startIndex...])    // "String"

स्विफ्ट 2 और 3

str = "My String"

** स्ट्रिंग इंडेक्स पर **

स्विफ्ट 2

let charAtIndex = String(str[str.startIndex.advancedBy(3)])  // charAtIndex = "S"

स्विफ्ट 3

str[str.index(str.startIndex, offsetBy: 3)]

SubString fromIndex toIndex

स्विफ्ट 2

let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)] // subStr = "Strin"

स्विफ्ट 3

str[str.index(str.startIndex, offsetBy: 3)...str.index(str.startIndex, offsetBy: 7)]

पहले एन चार

let first2Chars = String(str.characters.prefix(2)) // first2Chars = "My"

अंतिम n वर्ण

let last3Chars = String(str.characters.suffix(3)) // last3Chars = "ing"

24

एक्सकोड 7 जीएम बीज के रूप में स्विफ्ट 2.0

var text = "Hello, world!"

let firstChar = text[text.startIndex.advancedBy(0)] // "H"

Nth वर्ण के लिए, 0 को n-1 से प्रतिस्थापित करें।

संपादित करें: स्विफ्ट 3.0

text[text.index(text.startIndex, offsetBy: 0)]


nb स्ट्रिंग में कुछ वर्णों को हथियाने के सरल तरीके हैं

जैसे let firstChar = text.characters.first


23

यदि आप Cannot subscript a value of type 'String'...इस एक्सटेंशन का उपयोग करते हुए देखते हैं:

स्विफ्ट 3

extension String {
    subscript (i: Int) -> Character {
        return self[self.characters.index(self.startIndex, offsetBy: i)]
    }

    subscript (i: Int) -> String {
        return String(self[i] as Character)
    }

    subscript (r: Range<Int>) -> String {
        let start = index(startIndex, offsetBy: r.lowerBound)
        let end = index(startIndex, offsetBy: r.upperBound)
        return self[start..<end]
    }

    subscript (r: ClosedRange<Int>) -> String {
        let start = index(startIndex, offsetBy: r.lowerBound)
        let end = index(startIndex, offsetBy: r.upperBound)
        return self[start...end]
    }
}

स्विफ्ट 2.3

extension String {
    subscript(integerIndex: Int) -> Character {
        let index = advance(startIndex, integerIndex)
        return self[index]
    }

    subscript(integerRange: Range<Int>) -> String {
        let start = advance(startIndex, integerRange.startIndex)
        let end = advance(startIndex, integerRange.endIndex)
        let range = start..<end
        return self[range]
    }
}

स्रोत: http://oleb.net/blog/2014/07/swift-strings/


19

स्विफ्ट 2.2 समाधान:

निम्नलिखित विस्तार एक्सकोड 7 में काम करता है, यह इस समाधान का एक संयोजन है और स्विफ्ट 2.0 सिंटैक्स रूपांतरण है।

extension String {
    subscript(integerIndex: Int) -> Character {
        let index = startIndex.advancedBy(integerIndex)
        return self[index]
    }

    subscript(integerRange: Range<Int>) -> String {
        let start = startIndex.advancedBy(integerRange.startIndex)
        let end = startIndex.advancedBy(integerRange.endIndex)
        let range = start..<end
        return self[range]
    }
}

14

स्विफ्ट स्ट्रिंग क्लास यूटीएफ वर्णों के मूल समर्थन के कारण एक विशिष्ट सूचकांक में एक चरित्र प्राप्त करने की क्षमता प्रदान नहीं करता है। स्मृति में एक UTF वर्ण की परिवर्तनशील लंबाई एक चरित्र को सीधे कूदना असंभव बना देती है। इसका मतलब है कि आपको हर बार स्ट्रिंग पर मैन्युअल रूप से लूप करना होगा।

आप अपनी इच्छित अनुक्रमणिका तक वर्णों के माध्यम से लूप करने की विधि प्रदान करने के लिए स्ट्रिंग का विस्तार कर सकते हैं

extension String {
    func characterAtIndex(index: Int) -> Character? {
        var cur = 0
        for char in self {
            if cur == index {
                return char
            }
            cur++
        }
        return nil
    }
}

myString.characterAtIndex(0)!

3
आप पहले से ही तार के माध्यम से लूप कर सकते हैं: "फू" {
प्रिंट्लन

@Doobeh का मतलब था कि मैं पाश से गुजरता हूं और मेरे संपादन में ऊपर जैसा वास्तविक चरित्र
लौटाता हूं

अच्छा! यह मजेदार है कि आप इसके माध्यम से कैसे पुनरावृति कर सकते हैं, लेकिन एक सूचकांक के माध्यम से नहीं। स्विफ्ट की भावना pythonic लेकिन कठिन किनारों के साथ।
दोबह

मैंने चरित्र का एक मान का उपयोग myString.bridgeToObjectiveC().characterAtIndex(0)या (string as NSString ).characterAtIndex(0)रिटर्न पाया
चिह्नित करें

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

11

एक अलग नोट के रूप में, स्ट्रिंग के चरित्र-श्रृंखला प्रतिनिधित्व के लिए कुछ कार्य सीधे लागू होते हैं, जैसे:

var string = "Hello, playground"
let firstCharacter = string.characters.first // returns "H"
let lastCharacter = string.characters.last // returns "d"

परिणाम प्रकार चरित्र का है, लेकिन आप इसे एक स्ट्रिंग में डाल सकते हैं।

या यह:

let reversedString = String(string.characters.reverse())
// returns "dnuorgyalp ,olleH" 

:-)


11

स्विफ्ट 4

String(Array(stringToIndex)[index]) 

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

उदाहरण String(Array("HelloThere")[1])एक स्ट्रिंग के रूप में "ई" लौटाएगा।

(Array("HelloThere")[1] एक चरित्र के रूप में "ई" लौटाएगा।

स्विफ्ट स्ट्रिंग्स को सरणियों की तरह अनुक्रमित करने की अनुमति नहीं देता है, लेकिन यह काम करता है, जानवर बल शैली।


1
किसी अन्य मेमोरी लोकेशन पर संपूर्ण स्ट्रिंग सामग्री को डुप्लिकेट करना काउंटर-परफॉर्मेंट है, विशेष रूप से बड़े स्ट्रिंग्स के लिए। हमें सीधे मेमोरी एक्सेस जैसे सरल कार्यों के लिए अतिरिक्त मेमोरी आवंटन की आवश्यकता नहीं होनी चाहिए।
क्रिस्चियन

7

मेरा बहुत ही सरल उपाय:

स्विफ्ट 4.1:

let myString = "Test string"
let index = 0
let firstCharacter = myString[String.Index(encodedOffset: index)]

स्विफ्ट 5.1:

let firstCharacter = myString[String.Index.init(utf16Offset: index, in: myString)]

स्विफ्ट 4.1 में काम करता है
लीन

सरलतम समाधान और अब स्विफ्ट 5 उदाहरण के साथ :)
OhadM

@Linh Dao एन्कोडेडऑफ़सेट का उपयोग न करें। एन्कोडेडऑफ़सेट को हटा दिया गया है: एन्कोडेडऑफ़सेट को हटा दिया गया है क्योंकि अधिकांश आम उपयोग गलत है।
लियो डबस

@ ओम सरलतम का मतलब यह नहीं है कि यह सही है या कम से कम यह काम नहीं करेगा जैसा कि आप उम्मीद करते हैंlet flags = "🇺🇸🇧🇷" flags[String.Index(utf16Offset: 4, in: flags)] // "🇧🇷"
लियो डबस

1
@OhadM मेरी टिप्पणी सिर्फ एक चेतावनी थी। इसका उपयोग करने के लिए स्वतंत्र महसूस करें यदि आपको लगता है कि यह व्यवहार करता है कि आप कैसे उम्मीद करते हैं।
लियो डबस

6

आप इसे स्ट्रिंग में परिवर्तित करके ऐरे में कर सकते हैं और नीचे दिए गए सबस्क्रिप्ट का उपयोग करके इसे विशिष्ट सूचकांक द्वारा प्राप्त कर सकते हैं

var str = "Hello"
let s = Array(str)[2]
print(s)

1
ध्यान दें कि इस समाधान के परिणामस्वरूप सामग्री दोहराव होगी, जिससे यह कम प्रदर्शन करने योग्य मेमोरी वार और सीपीयू-वार होगा।
क्रिस्चियन

5

मेरा बस यही मुद्दा था। बस यह करें:

var aString: String = "test"
var aChar:unichar = (aString as NSString).characterAtIndex(0)

यह कई इमोजी और अन्य पात्रों के लिए विफल रहता है जो वास्तव में एक बार में "चरित्र" से अधिक बार लेते हैं NSString
25'17

5

Swift3

किसी विशेष स्ट्रिंग इंडेक्स पर कैरेक्टर तक पहुंचने के लिए आप सबस्क्रिप्ट सिंटैक्स का उपयोग कर सकते हैं।

let greeting = "Guten Tag!"
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index] // a

यात्रा करें

या हम स्विफ्ट 4 में एक स्ट्रिंग एक्सटेंशन कर सकते हैं

extension String {
    func getCharAtIndex(_ index: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: index)]
    }
}

उपयोग:

let foo = "ABC123"
foo.getCharAtIndex(2) //C

3

मेरा समाधान एक पंक्ति में है, कैडेना को दबाना स्ट्रिंग है और 4 वां स्थान है जिसे आप चाहते हैं:

let character = cadena[advance(cadena.startIndex, 4)]

सरल ... मुझे लगता है कि स्विफ्ट भविष्य के संस्करणों में सबस्ट्रिंग के बारे में अधिक चीजें शामिल करेगी।


1
क्या ऐसा var charAtIndex = string[advance(string.startIndex, 10)]सुलतान के जवाब में नहीं है?
मार्टिन आर

हां, यह उसी तरह का एक और उदाहरण है जैसा सुलतान ने कहा है। नकल के लिए क्षमा करें। :) यह आसान है दो लोगों को एक ही रास्ता मिल गया।
जूलियो सेसार फर्नांडीज मुअनोज़

3

स्विफ्ट 3: एक अन्य समाधान (खेल के मैदान में परीक्षण)

extension String {
    func substr(_ start:Int, length:Int=0) -> String? {
        guard start > -1 else {
            return nil
        }

        let count = self.characters.count - 1

        guard start <= count else {
            return nil
        }

        let startOffset = max(0, start)
        let endOffset = length > 0 ? min(count, startOffset + length - 1) : count

        return self[self.index(self.startIndex, offsetBy: startOffset)...self.index(self.startIndex, offsetBy: endOffset)]
    }
}

उपयोग:

let txt = "12345"

txt.substr(-1) //nil
txt.substr(0) //"12345"
txt.substr(0, length: 0) //"12345"
txt.substr(1) //"2345"
txt.substr(2) //"345"
txt.substr(3) //"45"
txt.substr(4) //"5"
txt.substr(6) //nil
txt.substr(0, length: 1) //"1"
txt.substr(1, length: 1) //"2"
txt.substr(2, length: 1) //"3"
txt.substr(3, length: 1) //"4"
txt.substr(3, length: 2) //"45"
txt.substr(3, length: 3) //"45"
txt.substr(4, length: 1) //"5"
txt.substr(4, length: 2) //"5"
txt.substr(5, length: 1) //nil
txt.substr(5, length: -1) //nil
txt.substr(-1, length: -1) //nil

2

स्विफ्ट 2.0 सबस्ट्रिंग के लिए अपडेट

public extension String {
    public subscript (i: Int) -> String {
        return self.substringWithRange(self.startIndex..<self.startIndex.advancedBy(i + 1))
    }

    public subscript (r: Range<Int>) -> String {
        get {
            return self.substringWithRange(self.startIndex.advancedBy(r.startIndex)..<self.startIndex.advancedBy(r.endIndex))
        }
    }

}

2

मुझे लगता है कि पहला चरित्र पाने के लिए एक तेज़ उत्तर हो सकता है:

let firstCharacter = aString[aString.startIndex]

यह बहुत सुंदर और प्रदर्शन से अधिक है:

let firstCharacter = Array(aString.characters).first

लेकिन .. यदि आप हेरफेर करना चाहते हैं और स्ट्रिंग्स के साथ अधिक संचालन करते हैं, तो आप सोच सकते हैं कि कोई एक्सटेंशन बना सकता है..इस दृष्टिकोण के साथ एक विस्तार है, यह पहले से ही यहां पोस्ट किए गए समान है:

extension String {
var length : Int {
    return self.characters.count
}

subscript(integerIndex: Int) -> Character {
    let index = startIndex.advancedBy(integerIndex)
    return self[index]
}

subscript(integerRange: Range<Int>) -> String {
    let start = startIndex.advancedBy(integerRange.startIndex)
    let end = startIndex.advancedBy(integerRange.endIndex)
    let range = start..<end
    return self[range]
}

}

लेकिन यह एक गंभीर विचार है !!

नीचे दिया गया विस्तार बहुत ही अयोग्य है। हर बार एक स्ट्रिंग को पूर्णांक के साथ एक्सेस किया जाता है, इसके शुरुआती इंडेक्स को चलाने के लिए O (n) फ़ंक्शन होता है। लीनियर लूप को दूसरे लीनियर लूप के अंदर चलाने का अर्थ है कि लूप के लिए यह गलती से O (n2) है - जैसे-जैसे स्ट्रिंग की लंबाई बढ़ती है, यह लूप चतुर्थांश बढ़ता जाता है।

ऐसा करने के बजाय आप पात्रों के स्ट्रिंग संग्रह का उपयोग कर सकते हैं।


2

स्विफ्ट 3

extension String {

    public func charAt(_ i: Int) -> Character {
        return self[self.characters.index(self.startIndex, offsetBy: i)]
    }

    public subscript (i: Int) -> String {
        return String(self.charAt(i) as Character)
    }

    public subscript (r: Range<Int>) -> String {
        return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
    }

    public subscript (r: CountableClosedRange<Int>) -> String {
        return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
    }

}

प्रयोग

let str = "Hello World"
let sub = str[0...4]

सहायक प्रोग्रामिंग टिप्स एंड ट्रिक्स (मेरे द्वारा लिखित)


2

सदस्यता प्राप्त करें और सेट करें (स्ट्रिंग और सबस्ट्रिंग) - स्विफ्ट 4.2

स्विफ्ट 4.2, एक्सकोड 10

मैंने @alecarlson के उत्तर के अपने उत्तर को आधारित कर दिया। एकमात्र बड़ा अंतर यह है कि आप Substringया एक Stringलौटाया जा सकता है (और कुछ मामलों में, एक एकल Character)। आप भी कर सकते हैं getऔर setसबस्क्रिप्ट। अंत में, मेरा थोड़ा अधिक बोझिल है और @alecarlson के उत्तर की तुलना में लंबा है , और जैसा कि, मेरा सुझाव है कि आप इसे एक स्रोत फ़ाइल में रखें।


एक्सटेंशन:

public extension String {
    public subscript (i: Int) -> Character {
        get {
            return self[index(startIndex, offsetBy: i)]
        }
        set (c) {
            let n = index(startIndex, offsetBy: i)
            replaceSubrange(n...n, with: "\(c)")
        }
    }
    public subscript (bounds: CountableRange<Int>) -> Substring {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[start ..< end]
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ..< end, with: s)
        }
    }
    public subscript (bounds: CountableClosedRange<Int>) -> Substring {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[start ... end]
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ... end, with: s)
        }

    }
    public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            return self[start ... end]
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            replaceSubrange(start ... end, with: s)
        }
    }
    public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[startIndex ... end]
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ... end, with: s)
        }
    }
    public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[startIndex ..< end]
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ..< end, with: s)
        }
    }

    public subscript (i: Int) -> String {
        get {
            return "\(self[index(startIndex, offsetBy: i)])"
        }
        set (c) {
            let n = index(startIndex, offsetBy: i)
            self.replaceSubrange(n...n, with: "\(c)")
        }
    }
    public subscript (bounds: CountableRange<Int>) -> String {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[start ..< end])"
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ..< end, with: s)
        }
    }
    public subscript (bounds: CountableClosedRange<Int>) -> String {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[start ... end])"
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ... end, with: s)
        }

    }
    public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            return "\(self[start ... end])"
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            replaceSubrange(start ... end, with: s)
        }
    }
    public subscript (bounds: PartialRangeThrough<Int>) -> String {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[startIndex ... end])"
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ... end, with: s)
        }
    }
    public subscript (bounds: PartialRangeUpTo<Int>) -> String {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[startIndex ..< end])"
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ..< end, with: s)
        }
    }

    public subscript (i: Int) -> Substring {
        get {
            return Substring("\(self[index(startIndex, offsetBy: i)])")
        }
        set (c) {
            let n = index(startIndex, offsetBy: i)
            replaceSubrange(n...n, with: "\(c)")
        }
    }
}
public extension Substring {
    public subscript (i: Int) -> Character {
        get {
            return self[index(startIndex, offsetBy: i)]
        }
        set (c) {
            let n = index(startIndex, offsetBy: i)
            replaceSubrange(n...n, with: "\(c)")
        }

    }
    public subscript (bounds: CountableRange<Int>) -> Substring {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[start ..< end]
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ..< end, with: s)
        }
    }
    public subscript (bounds: CountableClosedRange<Int>) -> Substring {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[start ... end]
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ... end, with: s)
        }
    }
    public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            return self[start ... end]
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            replaceSubrange(start ... end, with: s)
        }

    }
    public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[startIndex ... end]
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ..< end, with: s)
        }
    }
    public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return self[startIndex ..< end]
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ..< end, with: s)
        }
    }
    public subscript (i: Int) -> String {
        get {
            return "\(self[index(startIndex, offsetBy: i)])"
        }
        set (c) {
            let n = index(startIndex, offsetBy: i)
            replaceSubrange(n...n, with: "\(c)")
        }
    }
    public subscript (bounds: CountableRange<Int>) -> String {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[start ..< end])"
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ..< end, with: s)
        }
    }
    public subscript (bounds: CountableClosedRange<Int>) -> String {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[start ... end])"
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(start ... end, with: s)
        }

    }
    public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
        get {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            return "\(self[start ... end])"
        }
        set (s) {
            let start = index(startIndex, offsetBy: bounds.lowerBound)
            let end = index(endIndex, offsetBy: -1)
            replaceSubrange(start ... end, with: s)
        }
    }
    public subscript (bounds: PartialRangeThrough<Int>) -> String {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[startIndex ... end])"
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ... end, with: s)
        }
    }
    public subscript (bounds: PartialRangeUpTo<Int>) -> String {
        get {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            return "\(self[startIndex ..< end])"
        }
        set (s) {
            let end = index(startIndex, offsetBy: bounds.upperBound)
            replaceSubrange(startIndex ..< end, with: s)
        }
    }

    public subscript (i: Int) -> Substring {
        get {
            return Substring("\(self[index(startIndex, offsetBy: i)])")
        }
        set (c) {
            let n = index(startIndex, offsetBy: i)
            replaceSubrange(n...n, with: "\(c)")
        }
    }
}

यह अनावश्यक रूप से startIndex से दोनों अनुक्रमित (आरंभ और अंत) है। आप बस श्रंखला का उपयोग करके अंतिम इंडेक्स को भर सकते हैं। प्रारंभ में लियो और ऑफसेट इंडेक्स
लियो डबस

2

स्विफ्ट 4.2

यह उत्तर आदर्श है क्योंकि यह एक विस्तार में Stringअपने सभी Subsequences( Substring) का विस्तार करता है

public extension StringProtocol {

    public subscript (i: Int) -> Element {
        return self[index(startIndex, offsetBy: i)]
    }

    public subscript (bounds: CountableClosedRange<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return self[start...end]
    }

    public subscript (bounds: CountableRange<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return self[start..<end]
    }

    public subscript (bounds: PartialRangeUpTo<Int>) -> SubSequence {
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return self[startIndex..<end]
    }

    public subscript (bounds: PartialRangeThrough<Int>) -> SubSequence {
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return self[startIndex...end]
    }

    public subscript (bounds: CountablePartialRangeFrom<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        return self[start..<endIndex]
    }
}

प्रयोग

var str = "Hello, playground"

print(str[5...][...5][0])
// Prints ","

यह अनावश्यक रूप से इंडेक्स ( startऔर end) दोनों से ऑफसेट है startIndex। आप केवल endश्रंखला का उपयोग करके सूचकांक को भर सकते हैं। सूचकांक को और ऑफसेट कर सकते startहैं
लियो डबस

2

अब तक, सबस्क्रिप्ट (_ :) अनुपलब्ध है। साथ ही हम ऐसा नहीं कर सकते

str[0] 

स्ट्रिंग के साथ। हमें "String.Index" प्रदान करना है लेकिन, हम इस तरह से अपना खुद का इंडेक्स नंबर कैसे दे सकते हैं, इसके बजाय हम इसका उपयोग कर सकते हैं,

string[str.index(str.startIndex, offsetBy: 0)]

कृपया अपने उत्तर को संपादित करें और कोड-ओनली उत्तर पोस्ट करने के बजाय, यह बताकर कि आपका उत्तर समस्या का समाधान कैसे करता है, कुछ संदर्भ जोड़ें। समीक्षा से
पेडराम पारसियन

अनावश्यक ऑफसेट-आईएनजी क्यों कर रहे हैं? बस क्यों नहीं string[string.startIndex]? BTW, कोड सही ढंग से व्यवहार / संकलन नहीं करेगा, क्योंकि आपने दो भिन्न चर नामों का उपयोग किया था।
क्रिस्टिक

2

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

रेंज और आंशिक रेंज subscripting का उपयोग कर Stringके indicesसंपत्ति

@LeoDabus के अच्छे उत्तर की भिन्नता के रूप में , हम उत्तरार्द्ध के लिए कस्टम सदस्यता ( विशेष श्रेणियों और आंशिक श्रेणियों द्वारा) को लागू करते समय DefaultIndicesहमें indicesसंपत्ति पर वापस आने की अनुमति देने के उद्देश्य के साथ एक अतिरिक्त विस्तार जोड़ सकते हैं ।StringInt

extension DefaultIndices {
    subscript(at: Int) -> Elements.Index { index(startIndex, offsetBy: at) }
}

// Moving the index(_:offsetBy:) to an extension yields slightly
// briefer implementations for these String extensions.
extension String {
    subscript(range: Range<Int>) -> SubSequence {
        let start = indices[range.lowerBound]
        return self[start..<indices[start...][range.count]]
    }
    subscript(range: ClosedRange<Int>) -> SubSequence {
        let start = indices[range.lowerBound]
        return self[start...indices[start...][range.count]]
    }
    subscript(range: PartialRangeFrom<Int>) -> SubSequence {
        self[indices[range.lowerBound]...]
    }
    subscript(range: PartialRangeThrough<Int>) -> SubSequence {
        self[...indices[range.upperBound]]
    }
    subscript(range: PartialRangeUpTo<Int>) -> SubSequence {
        self[..<indices[range.upperBound]]
    }
}

let str = "foo bar baz bax"
print(str[4..<6]) // "ba"
print(str[4...6]) // "bar"
print(str[4...])  // "bar baz bax"
print(str[...6])  // "foo bar"
print(str[..<6])  // "foo ba"

धन का उपयोग करने की दिशा में मुझे इंगित करने के लिए @LeoDabus धन्यवाद indices(अन्य) के रूप में संपत्ति का उपयोग करने का विकल्प String!


1
एकमात्र नुकसान CountableClosedRange
startIndex

1
@LeoDabus मैं देख रहा हूँ। हाँ ज्यादातर लिनक्स लेकिन इन दिनों ज्यादा स्विफ्ट नहीं है: / swiftenvजब मैं करता हूं तो मैं उपयोग करता हूं, हालांकि, मुझे लगता है कि यह 4.2 के साथ अद्यतन किया जाएगा, तब भी कुछ हद तक।
डेजी

1
@LeoDabus आधुनिक स्विफ्ट के इस जवाब को अपडेट करने के लिए धन्यवाद!
dfri

1
@LeoDabus अच्छा काम! विवरण को बाद के समय में देखना होगा, लेकिन मुझे याद है कि मुझे यह कभी पसंद नहीं आया कि हमें कुछ आदेशित / गणनीय सेट प्रकारों के लिए फाउंडेशन पर वापस आना पड़ा।
dfri

1
धन्यवाद दोस्त!!!
सिंह डबस

2

स्विफ्ट 5.1.3:

स्ट्रिंग एक्सटेंशन जोड़ें:

extension String {

 func stringAt(_ i: Int) -> String { 
   return String(Array(self)[i]) 
 } 

 func charAt(_ i: Int) -> Character { 
  return Array(self)[i] 
 } 
}

let str = "Teja Kumar"
let str1: String = str.stringAt(2)  //"j"
let str2: Character = str.charAt(5)  //"k"

1
हर बार जब आप इस गुण को कॉल करते हैं तो पूरे स्ट्रिंग को एक वर्ण में बदल देगा।
लियो डबस

1

स्विफ्ट का Stringप्रकार एक characterAtIndexविधि प्रदान नहीं करता है क्योंकि कई तरीके हैं जिससे एक यूनिकोड स्ट्रिंग को एन्कोड किया जा सकता है। क्या आप UTF8, UTF16, या कुछ और के साथ जा रहे हैं?

आप और गुणों CodeUnitको पुनः प्राप्त करके संग्रह को एक्सेस कर सकते हैं। आप संपत्ति को पुनर्प्राप्त करके संग्रह भी एक्सेस कर सकते हैं।String.utf8String.utf16UnicodeScalarString.unicodeScalars

के NSStringकार्यान्वयन की भावना में , मैं एक unicharप्रकार लौट रहा हूं ।

extension String
{
    func characterAtIndex(index:Int) -> unichar
    {
        return self.utf16[index]
    }

    // Allows us to use String[index] notation
    subscript(index:Int) -> unichar
    {
        return characterAtIndex(index)
    }
}

let text = "Hello Swift!"
let firstChar = text[0]

यह उन पात्रों के लिए विफल हो जाएगा जिन्हें 16 बिट्स से अधिक भंडारण की आवश्यकता होती है। मूल रूप से, U + FFFF से परे कोई भी यूनिकोड वर्ण।
rmaddy

1

विषय को खिलाने और स्विफ्ट सबस्क्रिप्ट संभावनाओं को दिखाने के लिए, यहां थोड़ी स्ट्रिंग "सबस्ट्रिंग-टूलबॉक्स" सबस्क्रिप्ट आधारित है

ये विधियां सुरक्षित हैं और स्ट्रिंग इंडेक्स पर कभी नहीं जाती हैं

extension String {
    // string[i] -> one string char
    subscript(pos: Int) -> String { return String(Array(self)[min(self.length-1,max(0,pos))]) }

    // string[pos,len] -> substring from pos for len chars on the left
    subscript(pos: Int, len: Int) -> String { return self[pos, len, .pos_len, .left2right] }

    // string[pos, len, .right2left] -> substring from pos for len chars on the right
    subscript(pos: Int, len: Int, way: Way) -> String { return self[pos, len, .pos_len, way] }

    // string[range] -> substring form start pos on the left to end pos on the right
    subscript(range: Range<Int>) -> String { return self[range.startIndex, range.endIndex, .start_end, .left2right] }

    // string[range, .right2left] -> substring start pos on the right to end pos on the left
    subscript(range: Range<Int>, way: Way) -> String { return self[range.startIndex, range.endIndex, .start_end, way] }

    var length: Int { return countElements(self) }
    enum Mode { case pos_len, start_end }
    enum Way { case left2right, right2left }
    subscript(var val1: Int, var val2: Int, mode: Mode, way: Way) -> String {
        if mode == .start_end {
            if val1 > val2 { let val=val1 ; val1=val2 ; val2=val }
            val2 = val2-val1
        }
        if way == .left2right {
            val1 = min(self.length-1, max(0,val1))
            val2 = min(self.length-val1, max(1,val2))
        } else {
            let val1_ = val1
            val1 = min(self.length-1, max(0, self.length-val1_-val2 ))
            val2 = max(1, (self.length-1-val1_)-(val1-1) )
        }
        return self.bridgeToObjectiveC().substringWithRange(NSMakeRange(val1, val2))

        //-- Alternative code without bridge --
        //var range: Range<Int> = pos...(pos+len-1)
        //var start = advance(startIndex, range.startIndex)
        //var end = advance(startIndex, range.endIndex)
        //return self.substringWithRange(Range(start: start, end: end))
    }
}


println("0123456789"[3]) // return "3"

println("0123456789"[3,2]) // return "34"

println("0123456789"[3,2,.right2left]) // return "56"

println("0123456789"[5,10,.pos_len,.left2right]) // return "56789"

println("0123456789"[8,120,.pos_len,.right2left]) // return "01"

println("0123456789"[120,120,.pos_len,.left2right]) // return "9"

println("0123456789"[0...4]) // return "01234"

println("0123456789"[0..4]) // return "0123"

println("0123456789"[0...4,.right2left]) // return "56789"

println("0123456789"[4...0,.right2left]) // return "678" << because ??? range can wear endIndex at 0 ???

1

एक अजगर जैसा समाधान, जो आपको नकारात्मक सूचकांक का उपयोग करने की अनुमति देता है,

var str = "Hello world!"
str[-1]        // "!"

हो सकता है:

extension String {
    subscript (var index:Int)->Character{
        get {
            let n = distance(self.startIndex, self.endIndex)
            index %= n
            if index < 0 { index += n }
            return self[advance(startIndex, index)]
        }
    }
}

वैसे, यह पूरे अजगर के टुकड़ा संकेतन को स्थानांतरित करने के लिए इसके लायक हो सकता है


क्या आपको कुछ लिखने का मन है जो स्विफ्ट 4 के लिए संकलित करता है? अंतिम रिटर्न ... लाइन अग्रिम नहीं लगती है () फ़ंक्शन ऐसा नहीं है जो मुझे विश्वास है।
C0D3

1

आप स्ट्रिंग को सरणी की सरणी में भी बदल सकते हैं:

let text = "My Text"
let index = 2
let charSequence = text.unicodeScalars.map{ Character($0) }
let char = charSequence[index]

यह निरंतर समय में निर्दिष्ट सूचकांक पर चार पाने का तरीका है।

नीचे दिया गया उदाहरण निरंतर समय में नहीं चलता है, लेकिन इसके लिए रैखिक समय की आवश्यकता होती है। इसलिए यदि आप अनुक्रमणिका द्वारा स्ट्रिंग में बहुत अधिक खोज करते हैं तो ऊपर दी गई विधि का उपयोग करें।

let char = text[text.startIndex.advancedBy(index)]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.