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


354

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

विशेष रूप से मैं निम्नलिखित कोशिश कर रहा था:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

जहाँ दूसरी पंक्ति मुझे निम्नलिखित त्रुटि दे रही थी

मूल्य का प्रकार 'स्ट्रिंग' में कोई सदस्य नहीं है 'substringWithRange'

मैं देखता हूं कि Stringअब निम्नलिखित तरीके हैं:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

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


2
जो लोग स्ट्रिंग से सबस्ट्रिंग प्राप्त करना चाहते हैं के लिए stackoverflow.com/q/32305891/468724
इंद्र कुमार राठौर

या सबस्क्रिप्ट स्ट्रिंग या सबस्ट्रिंग stackoverflow.com/questions/24092884/...
सिंह Dabus

जवाबों:


831

यहां छवि विवरण दर्ज करें

सभी निम्नलिखित उदाहरणों का उपयोग करते हैं

var str = "Hello, playground"

स्विफ्ट 4

स्ट्रिंग्स को स्विफ्ट 4 में बहुत बड़ा ओवरहॉल मिला। जब आप स्ट्रिंग से कुछ विकल्प प्राप्त करते हैं, तो आपको एक के Substringबजाय एक प्रकार मिलता हैString । ऐसा क्यों है? स्विफ्ट में स्ट्रिंग्स मान प्रकार हैं। इसका मतलब है कि यदि आप एक नया बनाने के लिए एक स्ट्रिंग का उपयोग करते हैं, तो इसे कॉपी करना होगा। यह स्थिरता के लिए अच्छा है (कोई और आपकी जानकारी के बिना इसे बदलने वाला नहीं है) लेकिन दक्षता के लिए बुरा है।

दूसरी ओर, एरिकिंग, मूल स्ट्रिंग का एक संदर्भ है, जिसमें से यह आया था। यहाँ से एक छवि है प्रलेखन कि दर्शाता हुआ।

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

let myString = String(mySubstring)

यह सिर्फ सब्स्टिट्यूटिंग को कॉपी करेगा और पुराने स्ट्रिंग को रखने वाली मेमोरी को रिकवर किया जा सकता है । सबस्ट्रिंग (एक प्रकार के रूप में) का अर्थ अल्पकालिक होना है।

स्विफ्ट 4 में एक और बड़ा सुधार यह है कि स्ट्रिंग्स कलेक्शन (फिर से) हैं। इसका मतलब है कि आप एक संग्रह के लिए जो कुछ भी कर सकते हैं, आप एक स्ट्रिंग के लिए कर सकते हैं (सदस्यता का उपयोग करें, वर्णों पर पुनरावृति करें, फ़िल्टर करें, आदि)।

निम्नलिखित उदाहरण दिखाते हैं कि स्विफ्ट में एक विकल्प कैसे प्राप्त करें।

उपजाऊ होना

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

एक तार की शुरुआत

आप एक सबस्क्रिप्ट का उपयोग कर सकते हैं (स्विफ्ट 4 एक तरफा सीमा पर ध्यान दें):

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello

या prefix:

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello

या इससे भी आसान:

let mySubstring = str.prefix(5) // Hello

एक तार का अंत

सदस्यता का उपयोग करना:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground

या suffix:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground

या इससे भी आसान:

let mySubstring = str.suffix(10) // playground

ध्यान दें कि उपयोग करते समय suffix(from: index)मुझे उपयोग करके अंत से वापस गिनती करना था -10। यह जरूरी नहीं है कि बस का उपयोग करते समय suffix(x), जो सिर्फ xएक स्ट्रिंग के अंतिम पात्रों को लेता है ।

एक स्ट्रिंग में रेंज

फिर से हम यहां केवल सदस्यता का उपयोग करते हैं।

let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end

let mySubstring = str[range]  // play

में परिवर्तित Substringहो रहा हैString

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

let myString = String(mySubstring)

Intसूचकांक विस्तार का उपयोग करना ?

एयरस्पेड वेलोसिटी और ओले बेइमान द्वारा Intलेख स्ट्रिंग्स 3 इन स्विफ्ट 3 को पढ़ने के बाद मैं एक आधारित सूचकांक विस्तार का उपयोग करने में संकोच कर रहा हूं । हालांकि स्विफ्ट 4 में, स्ट्रिंग्स संग्रह हैं, स्विफ्ट टीम ने जानबूझकर Intअनुक्रमित का उपयोग नहीं किया है । यह अभी भी है String.Index। यह स्विफ्ट वर्णों को यूनिकोड कोडपॉइंट्स की अलग-अलग संख्याओं से बना होता है। वास्तविक सूचकांक को प्रत्येक स्ट्रिंग के लिए विशिष्ट रूप से गणना करना होगा।

मुझे कहना है, मुझे आशा है कि स्विफ्ट टीम String.Indexभविष्य में दूर रहने का एक रास्ता खोज लेती है । लेकिन जब तक मैं उनके एपीआई का उपयोग करना चुन रहा हूं। यह मुझे याद रखने में मदद करता है कि स्ट्रिंग जोड़तोड़ केवल साधारण Intसूचकांक लुकअप नहीं हैं।


9
डिसक्रिएशन के लिए Thx। अच्छी तरह से हकदार हैं। Apple ने इसे ओवरकंप्लीट किया। सबस्ट्रिंग को स्ट्रिंग के समान आसान होना चाहिए।
टेडी

वास्तव में अच्छी व्याख्या। एक छोटी सी बात को छोड़कर garbage collected;-) मुझे उम्मीद है कि यहां के लोग जानते हैं कि स्विफ्ट में कोई कचरा संग्रह नहीं है।
क्रिश्चियन एंकर नम

@ChristianAnchorDampf, टिप्पणी करने के लिए समय निकालने के लिए धन्यवाद। मैंने कचरा इकट्ठा किया। कैसा है नया शब्दांकन?
सुरगाछ

क्या कमाल का जवाब है सर !!
डेविदेव

194

मैं वास्तव में स्विफ्ट के स्ट्रिंग एक्सेस मॉडल पर निराश हूं: सब कुछ होना चाहिए Index। मैं चाहता हूं कि स्ट्रिंग के आई-वें चरित्र का उपयोग करना है Int, न कि अनाड़ी सूचकांक और अग्रिम (जो हर बड़ी रिलीज के साथ बदलने के लिए होता है)। इसलिए मैंने इसके लिए एक एक्सटेंशन बनाया String:

extension String {
    func index(from: Int) -> Index {
        return self.index(startIndex, offsetBy: from)
    }

    func substring(from: Int) -> String {
        let fromIndex = index(from: from)
        return String(self[fromIndex...])
    }

    func substring(to: Int) -> String {
        let toIndex = index(from: to)
        return String(self[..<toIndex])
    }

    func substring(with r: Range<Int>) -> String {
        let startIndex = index(from: r.lowerBound)
        let endIndex = index(from: r.upperBound)
        return String(self[startIndex..<endIndex])
    }
}

let str = "Hello, playground"
print(str.substring(from: 7))         // playground
print(str.substring(to: 5))           // Hello
print(str.substring(with: 7..<11))    // play

5
इंडेक्स बहुत उपयोगी होते हैं क्योंकि एक चरित्र एक से अधिक बाइट हो सकता है। कोशिश करेंlet str = "🇨🇭🇩🇪🇺🇸Hello" print(str.substring(to: 2))
वादी

110
हां, मैं समझता हूं कि एक चरित्र (यानी विस्तारित ग्रैफेम क्लस्टर ) कई बाइट ले सकता है। मेरी हताशा यह है कि हमें एक स्ट्रिंग के पात्रों तक पहुंचने के लिए वर्बोज़ इंडेक्स-एडवांसिंग पद्धति का उपयोग करना होगा। क्यों नहीं स्विफ्ट टीम बस कुछ ओवरलोड्स को जोड़ने के लिए कोर लाइब्रेरी से दूर कर सकती है। यदि मैं टाइप करता हूं str[5], तो मैं वर्ण 5 पर चरित्र को एक्सेस करना चाहता हूं, चाहे वह चरित्र कुछ भी प्रतीत हो या उसे कितने बाइट्स लगते हैं। क्या डेवलपर की उत्पादकता के बारे में सब कुछ नहीं है?
कोड अलग

6
@ रेनीपेट का मानना ​​है कि Apple समस्या को पहचानता है और परिवर्तन आ रहा है। गिटहब पर स्विफ्ट इवोल्यूशन पेज के अनुसार: "स्विफ्ट 4 डिफ़ॉल्ट रूप से यूनिकोड शुद्धता को बनाए रखते हुए तारों को अधिक शक्तिशाली और आसान उपयोग करने के लिए ढूंढता है"। यह अस्पष्ट है लेकिन चलो हमारी आशाओं को बनाए रखें
कोड अलग

3
@CodeDifferent ऐप्पल ने सबस्क्रिप्ट कैरेक्टर एक्सेस क्यों नहीं जोड़ा? ताकि लोग समझें कि यह बुरा काम है। मूल रूप से यदि आप 0..string.count में i के लिए करते हैं तो सब्सक्राइब का उपयोग करते हुए जो डबल लूप होगा, हुड इंडेक्स के तहत स्ट्रिंग के प्रत्येक बाइट से गुजरने के लिए यह पता लगाना है कि अगला चरित्र कौन सा है। यदि आप सूचकांक का उपयोग करते हुए लूप करते हैं, तो आप केवल एक बार स्ट्रिंग पर पुनरावृति करते हैं। Btw, यह खुद से नफरत है, लेकिन है कि सबस्क्रिप्ट के पीछे तर्क में तेजी से स्ट्रिंग पर उपलब्ध नहीं है।
रायमुंडस सकलौसक

4
@RaundundasSakalauskas कि तर्क मेरे द्वारा उड़ान नहीं भरता है। C # में यूनिकोड शुद्धता और पूर्णांक सबस्क्रिप्टिंग है, जो वास्तव में सुविधाजनक है। स्विफ्ट 1 में, Apple चाहता था कि डेवलपर्स countElement(str)लंबाई खोजने के लिए उपयोग करें। स्विफ्ट 3 में, Apple ने स्ट्रिंग को अनुरूप नहीं बनाया Sequenceऔर str.charactersइसके बजाय सभी को उपयोग करने के लिए मजबूर किया। ये लोग बदलाव करने से नहीं डरते। पूर्णांक पर उनकी हठ वास्तव में समझने में मुश्किल है
कोड अलग

102

स्विफ्ट 5 एक्सटेंशन:

extension String {
    subscript(_ range: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
        let end = index(start, offsetBy: min(self.count - range.lowerBound, 
                                             range.upperBound - range.lowerBound))
        return String(self[start..<end])
    }

    subscript(_ range: CountablePartialRangeFrom<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
         return String(self[start...])
    }
}

उपयोग:

let s = "hello"
s[0..<3] // "hel"
s[3...]  // "lo"

या यूनिकोड:

let s = "😎🤣😋"
s[0..<1] // "😎"

2
इतना बेहतर, इस विस्तार को पोस्ट करने के लिए धन्यवाद! मुझे लगता है कि पायथन से आ रहा है, स्विफ्ट इस्तेमाल करने के लिए आवश्यक से बहुत कठिन है। ऐसा लगता है कि ऑब्जेक्टिव सी से स्विफ्ट तक दूसरी दिशा में जाने वाले लोगों के लिए ज्यादा सकारात्मक पुष्टि है।
user3064009

1
@ लेओन मैंने अभी इसे हटा दिया है। 4.1 से पहले, countकेवल पर उपलब्ध थाself.characters
लो ज़ेल

1
क्या इस विशेष विस्तार के साथ देखने के लिए कोई गोटे हैं? Apple ने ऐसा कुछ क्यों नहीं किया?
एंडज

1
@ और यह बहुत अक्षम है। यह स्ट्रिंग की शुरुआत से शुरू होता है - दो बार - और वहाँ से हर वर्ण को "रेंज" में दो बार पार्स करना पड़ता है।
करीमन

3
आपको एक एक्सटेंशनCountableClosedRange<Int> जोड़ने की भी आवश्यकता होगी जो यदि आप लिखना चाहते हैं, जैसे s[0...2]
क्रिस फ्रेडरिक

24

स्विफ्ट 4 और 5:

extension String {
  subscript(_ i: Int) -> String {
    let idx1 = index(startIndex, offsetBy: i)
    let idx2 = index(idx1, offsetBy: 1)
    return String(self[idx1..<idx2])
  }

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

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

इसका इस्तेमाल कैसे करें:

"एबीसीड" [0] -> "ए"

"एबीसीड" [0 ... 2] -> "एबीसी"

"एबीसीड" [2 .. <4] -> "सीडी"


20

स्विफ्ट 4

स्विफ्ट में 4 के Stringअनुरूप है Collection। इसके बजाय substring, हमें अब एक का उपयोग करना चाहिए subscript.यदि आप केवल शब्द "play"को बाहर निकालना चाहते हैं "Hello, playground", तो आप इसे इस तरह से कर सकते हैं:

var str = "Hello, playground"
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let result = str[start..<end] // The result is of type Substring

यह जानना दिलचस्प है, कि ऐसा करने से आपको Substringबदले की भावना मिलेगी String। यह Substringमूल स्ट्रिंग के साथ अपने भंडारण को साझा करने के रूप में तेज और कुशल है । हालाँकि इस तरह से मेमोरी शेयर करने से मेमोरी लीक भी आसानी से हो सकती है।

यही कारण है कि आपको मूल स्ट्रिंग को साफ करने के लिए एक बार, परिणाम को एक नए स्ट्रिंग में कॉपी करना चाहिए। आप सामान्य कंस्ट्रक्टर का उपयोग करके ऐसा कर सकते हैं:

let newString = String(result)

आप Substring[Apple प्रलेखन] में नए वर्ग पर अधिक जानकारी पा सकते हैं । 1

इसलिए, यदि आप उदाहरण के लिए एक Rangeपरिणाम के रूप में मिलता है, तो आप NSRegularExpressionनिम्नलिखित एक्सटेंशन का उपयोग कर सकते हैं:

extension String {

    subscript(_ range: NSRange) -> String {
        let start = self.index(self.startIndex, offsetBy: range.lowerBound)
        let end = self.index(self.startIndex, offsetBy: range.upperBound)
        let subString = self[start..<end]
        return String(subString)
    }

}

यदि आपका कोड क्रैश हो जाएगा तो रेंज.उपरबाउंड> स्ट्रिंग की लंबाई है। इसके अलावा, एक नमूना उपयोग भी उपयोगी होगा, क्योंकि मैं स्विफ्ट में ग्राहकों से परिचित नहीं था। आप कुछ को शामिल कर सकते हैं जैसे datePartOnly = "2018-01-04-08: 00" [NSMakeRange (0, 10)]]। इसके अलावा, बहुत अच्छा जवाब, +1 :)।
डीसीपी

आजकल यह अजीब बात है: text[Range( nsRange , in: text)!]
फेटी

10

यहां एक फ़ंक्शन है जो प्रारंभ और अंत सूचक प्रदान किए जाने पर किसी दिए गए सबस्ट्रिंग का विकल्प देता है। पूर्ण संदर्भ के लिए आप नीचे दिए गए लिंक पर जा सकते हैं।

func substring(string: String, fromIndex: Int, toIndex: Int) -> String? {
    if fromIndex < toIndex && toIndex < string.count /*use string.characters.count for swift3*/{
        let startIndex = string.index(string.startIndex, offsetBy: fromIndex)
        let endIndex = string.index(string.startIndex, offsetBy: toIndex)
        return String(string[startIndex..<endIndex])
    }else{
        return nil
    }
}

यहाँ उस ब्लॉग पोस्ट का लिंक दिया गया है जो मैंने स्विफ्ट में स्ट्रिंग हेरफेर से निपटने के लिए बनाया है। तेज में हेरफेर हेरफेर (कवर स्विफ्ट 4 के रूप में अच्छी तरह से)

या आप इस गीदड़ को जिठूब पर देख सकते हैं


9

मेरी वही शुरुआती प्रतिक्रिया थी। मुझे इस बात पर भी निराशा हुई कि हर बड़ी रिलीज़ में सिंटैक्स और ऑब्जेक्ट्स में कितना बदलाव आता है।

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

इसलिए मैंने Apple इंजीनियरों द्वारा लगाए गए प्रयासों को पहचानने और उनका सम्मान करने का फैसला किया और इस "भयावह" दृष्टिकोण के साथ आने पर उनकी मानसिकता को समझने के लिए मेरी ओर से किया।

एक्सटेंशन बनाने के बजाय जो आपके जीवन को आसान बनाने के लिए सिर्फ एक समाधान है (मैं कह रहा हूं कि वे गलत या महंगे नहीं हैं), यह पता नहीं क्यों स्ट्रिंग्स को अब काम करने के लिए डिज़ाइन किया गया है।

उदाहरण के लिए, मेरे पास यह कोड था जो स्विफ्ट 2.2 पर काम कर रहा था:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(2)

और सबस्ट्रिंग का उपयोग करते हुए काम करने के लिए एक ही दृष्टिकोण प्राप्त करने की कोशिश करने के बाद, मैंने आखिरकार स्ट्रिंग्स को एक द्विदिश संग्रह के रूप में मानने की अवधारणा को समझा, जिसके लिए मैंने एक ही कोड के इस संस्करण के साथ समाप्त किया:

let rString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let gString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let bString = String(cString.characters.prefix(2))

मुझे आशा है कि यह योगदान देता है ...


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

5

एक ही हताशा, यह नहीं होना चाहिए कि मुश्किल ...

मैंने बड़े पाठ से स्थानापन्न (ओं) के लिए स्थान पाने के इस उदाहरण को संकलित किया:

//
// Play with finding substrings returning an array of the non-unique words and positions in text
//
//

import UIKit

let Bigstring = "Why is it so hard to find substrings in Swift3"
let searchStrs : Array<String>? = ["Why", "substrings", "Swift3"]

FindSubString(inputStr: Bigstring, subStrings: searchStrs)


func FindSubString(inputStr : String, subStrings: Array<String>?) ->    Array<(String, Int, Int)> {
    var resultArray : Array<(String, Int, Int)> = []
    for i: Int in 0...(subStrings?.count)!-1 {
        if inputStr.contains((subStrings?[i])!) {
            let range: Range<String.Index> = inputStr.range(of: subStrings![i])!
            let lPos = inputStr.distance(from: inputStr.startIndex, to: range.lowerBound)
            let uPos = inputStr.distance(from: inputStr.startIndex, to: range.upperBound)
            let element = ((subStrings?[i])! as String, lPos, uPos)
            resultArray.append(element)
        }
    }
    for words in resultArray {
        print(words)
    }
    return resultArray
}

रिटर्न ("क्यों", 0, 3) ("सबस्ट्रिंग", 26, 36) ("स्विफ्ट 3", 40, 46)


3
यह कुछ कोड है, लेकिन वास्तव में यह स्पष्ट नहीं करता है कि स्विफ्ट 3 में स्ट्रिंग इंडेक्सिंग और सबस्ट्रिंग कैसे काम करते हैं।
रॉबर्ट

5

मैं स्विफ्ट 3 में नया हूं, लेकिन Stringसादृश्य के लिए (इंडेक्स) सिंटैक्स को देखकर मुझे लगता है कि इंडेक्स एक "पॉइंटर" की तरह है जो स्ट्रिंग के लिए विवश है और इंट एक स्वतंत्र वस्तु के रूप में मदद कर सकता है। आधार + ऑफसेट सिंटैक्स का उपयोग करना, फिर हम कोड bellow के साथ स्ट्रिंग से i-th वर्ण प्राप्त कर सकते हैं:

let s = "abcdefghi"
let i = 2
print (s[s.index(s.startIndex, offsetBy:i)])
// print c

स्ट्रिंग (श्रेणी) सिंटैक्स का उपयोग करके स्ट्रिंग से वर्णों (अनुक्रमित) की एक श्रृंखला के लिए हम कोड bellow के साथ i-th से f-th वर्णों तक प्राप्त कर सकते हैं:

let f = 6
print (s[s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 )])
//print cdefg

String.substring (श्रेणी) का उपयोग करके स्ट्रिंग से एक विकल्प (श्रेणी) के लिए हम कोड बेलो का उपयोग करके सबस्ट्रिंग प्राप्त कर सकते हैं:

print (s.substring (with:s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 ) ) )
//print cdefg

टिप्पणियाँ:

  1. I-th और f-th की शुरुआत 0 से होती है।

  2. एफ-वें के लिए, मैं ऑफ़सेटबीवाई का उपयोग करता हूं: एफ + 1, क्योंकि सदस्यता की सीमा का उपयोग .. <(आधा-खुला ऑपरेटर), जिसमें एफ-वें स्थिति शामिल नहीं है।

  3. निश्चित रूप से अमान्य सूचकांक जैसी मान्य त्रुटियों को शामिल करना चाहिए।


5

स्विफ्ट 4+

extension String {
    func take(_ n: Int) -> String {
        guard n >= 0 else {
            fatalError("n should never negative")
        }
        let index = self.index(self.startIndex, offsetBy: min(n, self.count))
        return String(self[..<index])
    }
}

यदि स्ट्रिंग छोटी है, तो पहले n वर्णों की संपूर्णता या संपूर्ण स्ट्रिंग लौटाता है। (इससे प्रेरित: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html )

उदाहरण:

let text = "Hello, World!"
let substring = text.take(5) //Hello

4

मैं काफी मैकेनिकल सोच वाला हूं। यहां मूल बातें हैं ...

स्विफ्ट 4 स्विफ्ट 5

  let t = "abracadabra"

  let start1 = t.index(t.startIndex, offsetBy:0)
  let   end1 = t.index(t.endIndex, offsetBy:-5)
  let start2 = t.index(t.endIndex, offsetBy:-5)
  let   end2 = t.index(t.endIndex, offsetBy:0)

  let t2 = t[start1 ..< end1]
  let t3 = t[start2 ..< end2]                

  //or a shorter form 

  let t4 = t[..<end1]
  let t5 = t[start2...]

  print("\(t2) \(t3) \(t)")
  print("\(t4) \(t5) \(t)")

  // result:
  // abraca dabra abracadabra

परिणाम एक विकल्प है, जिसका अर्थ है कि यह मूल स्ट्रिंग का एक हिस्सा है। एक पूर्ण विकसित अलग स्ट्रिंग प्राप्त करने के लिए बस जैसे उपयोग करें

    String(t3)
    String(t4)

यही है वह जो मेरे द्वारा उपयोग किया जाता है:

    let mid = t.index(t.endIndex, offsetBy:-5)
    let firstHalf = t[..<mid]
    let secondHalf = t[mid...]

3

स्विफ्ट 4

extension String {
    subscript(_ i: Int) -> String {
        let idx1 = index(startIndex, offsetBy: i)
        let idx2 = index(idx1, offsetBy: 1)
        return String(self[idx1..<idx2])
    }
}

let s = "hello"

s[0]    // h
s[1]    // e
s[2]    // l
s[3]    // l
s[4]    // o

2

मैंने इसके लिए एक सरल एक्सटेंशन बनाया (स्विफ्ट 3)

extension String {
    func substring(location: Int, length: Int) -> String? {
        guard characters.count >= location + length else { return nil }
        let start = index(startIndex, offsetBy: location)
        let end = index(startIndex, offsetBy: location + length)
        return substring(with: start..<end)
    }
}

2

एक अधिक सामान्य कार्यान्वयन का उपयोग करता है:

यह तकनीक अभी भी indexस्विफ्ट के मानकों को बनाए रखने के लिए उपयोग करती है, और एक पूर्ण चरित्र का अर्थ करती है।

extension String
{
    func subString <R> (_ range: R) -> String? where R : RangeExpression, String.Index == R.Bound
    {
        return String(self[range])
    }

    func index(at: Int) -> Index
    {
        return self.index(self.startIndex, offsetBy: at)
    }
}

तीसरे वर्ण से उप स्ट्रिंग करने के लिए:

let item = "Fred looks funny"
item.subString(item.index(at: 2)...) // "ed looks funny"

मैंने ऊंट subStringका उपयोग यह इंगित करने के लिए किया है कि यह रिटर्न ए Stringऔर ए नहीं है Substring


2

ऊपर की ओर बिल्डिंग मुझे नॉन-प्रिंटिंग कैरेक्टर को छोड़ने वाले नॉन-प्रिन्टिंग कैरेक्टर पर एक स्ट्रिंग को विभाजित करने की आवश्यकता थी। मैंने दो तरीके विकसित किए:

var str = "abc\u{1A}12345sdf"
let range1: Range<String.Index> = str.range(of: "\u{1A}")!
let index1: Int = str.distance(from: str.startIndex, to: range1.lowerBound)
let start = str.index(str.startIndex, offsetBy: index1)
let end = str.index(str.endIndex, offsetBy: -0)
let result = str[start..<end] // The result is of type Substring
let firstStr = str[str.startIndex..<range1.lowerBound]

जो मैंने ऊपर के कुछ उत्तरों का उपयोग करके एक साथ रखा।

क्योंकि एक स्ट्रिंग एक संग्रह है जो मैंने तब किया था:

var fString = String()
for (n,c) in str.enumerated(){

*if c == "\u{1A}" {
    print(fString);
    let lString = str.dropFirst(n + 1)
    print(lString)
    break
   }
 fString += String(c)
}*

जो मेरे लिए अधिक सहज था। कौन सा सबसे अच्छा है? मेरे पास यह बताने का कोई तरीका नहीं है कि वे दोनों स्विफ्ट 5 के साथ काम करते हैं


आपके उत्तर के लिए धन्यवाद। क्या स्विफ्ट 5 में स्ट्रिंग्स के बारे में कुछ अलग है? मेरे पास अभी तक इसके साथ खेलने का समय नहीं है।
सर्ग

वे ऐसा कहते हैं लेकिन मुझे इस पर गौर करने का मौका नहीं मिला।
जेरेमी एंड्रयूज

1

स्विफ्ट 4

"पदार्थ" ( https://developer.apple.com/documentation/swift/substring )

let greeting = "Hi there! It's nice to meet you! 👋"
let endOfSentence = greeting.index(of: "!")!
let firstSentence = greeting[...endOfSentence]
// firstSentence == "Hi there!"

विस्तार स्ट्रिंग का उदाहरण:

private typealias HowDoYouLikeThatElonMusk = String
private extension HowDoYouLikeThatElonMusk {

    subscript(_ from: Character?, _ to: Character?, _ include: Bool) -> String? {
        if let _from: Character = from, let _to: Character = to {
            let dynamicSourceForEnd: String = (_from == _to ? String(self.reversed()) : self)
            guard let startOfSentence: String.Index = self.index(of: _from),
                let endOfSentence: String.Index = dynamicSourceForEnd.index(of: _to) else {
                return nil
            }

            let result: String = String(self[startOfSentence...endOfSentence])
            if include == false {
                guard result.count > 2 else {
                        return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        } else if let _from: Character = from {
            guard let startOfSentence: String.Index = self.index(of: _from) else {
                return nil
            }
            let result: String = String(self[startOfSentence...])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)...])
            }
            return result
        } else if let _to: Character = to {
            guard let endOfSentence: String.Index = self.index(of: _to) else {
                    return nil
            }
            let result: String = String(self[...endOfSentence])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        }
        return nil
    }
}

एक्सटेंशन स्ट्रिंग का उपयोग करने का उदाहरण:

let source =                                   ">>>01234..56789<<<"
// include = true
var from =          source["3", nil, true]  //       "34..56789<<<"
var to =            source[nil, "6", true]  // ">>>01234..56"
var fromTo =        source["3", "6", true]  //       "34..56"
let notFound =      source["a", nil, true]  // nil
// include = false
from =              source["3", nil, false] //        "4..56789<<<"
to =                source[nil, "6", false] // ">>>01234..5"
fromTo =            source["3", "6", false] //        "4..5"
let outOfBounds =   source[".", ".", false] // nil

let str = "Hello, playground"
let hello = str[nil, ",", false] // "Hello"

-1

स्विफ्ट 5
let desiredIndex: Int = 7 let substring = str[String.Index(encodedOffset: desiredIndex)...]
यह विकल्प चर आपको परिणाम देगा।
बस यहां Int को Index में बदल दिया जाता है और फिर आप स्ट्रिंग्स को विभाजित कर सकते हैं। जब तक आपको त्रुटियाँ नहीं मिलेंगी।


2
ये गलत है। चरित्र में एक या एक से अधिक बाइट्स हो सकते हैं। यह केवल एससीआई पाठ के साथ काम करता है।
लियो डबस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.