स्विफ्ट में रेंज कैसे बनाएं?


103

ऑब्जेक्टिव-सी में हम NSRange का उपयोग करके रेंज बनाते हैं

NSRange range;

तो स्विफ्ट में रेंज कैसे बनाएं?


3
आपको किस सीमा की आवश्यकता है? स्विफ्ट स्ट्रिंग्स का उपयोग करते हैं Range<String.Index>, लेकिन कभी-कभी इसके साथ काम करना आवश्यक होता है NSStringऔर NSRangeइसलिए कुछ और संदर्भ उपयोगी होंगे। - लेकिन stackoverflow.com/questions/24092884/… पर एक नज़र डालें ।
मार्टिन आर

जवाबों:


256

स्विफ्ट 4 के लिए अपडेट किया गया

स्विफ्ट रेंज की तुलना में अधिक जटिल हैं NSRange, और उन्हें स्विफ्ट 3 में कोई आसान नहीं मिला। यदि आप इस जटिलता के पीछे के तर्क को समझने की कोशिश करना चाहते हैं, तो इसे पढ़ें और इसे पढ़ें । मैं बस आपको दिखाऊंगा कि उन्हें कैसे बनाना है और जब आप उनका उपयोग कर सकते हैं।

बंद रंग: a...b

यह रेंज ऑपरेटर एक स्विफ्ट रेंज बनाता है जिसमें तत्व a और तत्व दोनों शामिल हैं b, भले ही bएक प्रकार (जैसे Int.max) के लिए अधिकतम संभव मूल्य हो । दो अलग-अलग प्रकार की बंद श्रेणियां हैं: ClosedRangeऔर CountableClosedRange

1। ClosedRange

स्विफ्ट में सभी श्रेणियों के तत्व तुलनीय हैं (यानी, वे तुलनात्मक प्रोटोकॉल के अनुरूप हैं)। यह आपको एक संग्रह से सीमा में तत्वों का उपयोग करने की अनुमति देता है। यहाँ एक उदाहरण है:

let myRange: ClosedRange = 1...3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]

हालाँकि, ClosedRangeयह गणना योग्य नहीं है (यानी, यह अनुक्रम प्रोटोकॉल के अनुरूप नहीं है)। इसका मतलब है कि आप एक forलूप के साथ तत्वों पर पुनरावृति नहीं कर सकते । उसके लिए आपको चाहिए CountableClosedRange

2। CountableClosedRange

यह पिछले एक के समान है सिवाय अब सीमा को भी पुनरावृत्त किया जा सकता है।

let myRange: CountableClosedRange = 1...3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]

for index in myRange {
    print(myArray[index])
}

हाफ-ओपन रेंज: a..<b

इस रेंज ऑपरेटर में तत्व शामिल हैं, aलेकिन तत्व नहींb । ऊपर की तरह, दो अलग-अलग प्रकार की अर्ध-खुली सीमाएं हैं: Rangeऔर CountableRange

1। Range

के रूप में ClosedRange, आप एक के साथ एक संग्रह के तत्वों का उपयोग कर सकते हैं Range। उदाहरण:

let myRange: Range = 1..<3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]

फिर, हालांकि, आप एक से अधिक पुनरावृति नहीं कर सकते Range इसे क्योंकि यह केवल तुलनीय है, स् थिर नहीं है।

2। CountableRange

A CountableRangeपुनरावृत्ति की अनुमति देता है।

let myRange: CountableRange = 1..<3

let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]

for index in myRange {
    print(myArray[index])
}

NSRange

आप NSRangeस्विफ्ट ( उदाहरण के लिए जिम्मेदार स्ट्रिंग्स बनाते समय ) में अभी भी कई बार उपयोग कर सकते हैं , इसलिए यह जानना उपयोगी है कि कैसे बनाया जाए।

let myNSRange = NSRange(location: 3, length: 2)

ध्यान दें कि यह स्थान और लंबाई है , न कि अनुक्रमणिका और अंत अनुक्रमणिका। यहाँ उदाहरण स्विफ्ट रेंज के अर्थ में समान है 3..<5। हालांकि, चूंकि प्रकार भिन्न हैं, वे विनिमेय नहीं हैं।

स्ट्रिंग्स के साथ रंग

...और ..<रेंज ऑपरेटरों पर्वतमाला बनाने की एक आशुलिपि तरीका है। उदाहरण के लिए:

let myRange = 1..<3

एक ही रेंज बनाने का लंबा हाथ तरीका होगा

let myRange = CountableRange<Int>(uncheckedBounds: (lower: 1, upper: 3)) // 1..<3

आप देख सकते हैं कि यहाँ सूचकांक प्रकार है IntStringहालांकि, इसके लिए काम नहीं करता है , क्योंकि स्ट्रिंग्स अक्षर से बने होते हैं और सभी वर्ण समान आकार के नहीं होते हैं। (पढ़ें इस अधिक जानकारी के लिए ।) एक इमोजी जैसे info, उदाहरण के लिए, "b" अक्षर से अधिक जगह लेता है।

NSRange के साथ समस्या

साथ प्रयोग करके देखें NSRangeऔर एक NSStringइमोजी के साथ और आप देखेंगे कि मैं क्या मतलब है। सरदर्द।

let myNSRange = NSRange(location: 1, length: 3)

let myNSString: NSString = "abcde"
myNSString.substring(with: myNSRange) // "bcd"

let myNSString2: NSString = "a😀cde"
myNSString2.substring(with: myNSRange) // "😀c"    Where is the "d"!?

स्माइली फेस स्टोर करने के लिए दो UTF-16 कोड यूनिट लेता है, इसलिए यह "d" को शामिल न करने का अप्रत्याशित परिणाम देता है।

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

इस वजह से, स्विफ्ट स्ट्रिंग्स के साथ, आप उपयोग करते हैं Range<String.Index>, नहींRange<Int> । स्ट्रिंग इंडेक्स की गणना एक विशेष स्ट्रिंग के आधार पर की जाती है ताकि यह पता चल सके कि क्या कोई इमोजी या विस्तारित ग्रैफेम क्लस्टर हैं।

उदाहरण

var myString = "abcde"
let start = myString.index(myString.startIndex, offsetBy: 1)
let end = myString.index(myString.startIndex, offsetBy: 4)
let myRange = start..<end
myString[myRange] // "bcd"

myString = "a😀cde"
let start2 = myString.index(myString.startIndex, offsetBy: 1)
let end2 = myString.index(myString.startIndex, offsetBy: 4)
let myRange2 = start2..<end2
myString[myRange2] // "😀cd"

एक तरफा सीमाएँ: a...और ...bऔर..<b

स्विफ्ट में 4 चीजें थोड़ी सरल हुईं। जब भी किसी रेंज का शुरुआती या अंतिम बिंदु पता लगाया जा सकता है, तो आप इसे छोड़ सकते हैं।

इंट

आप एक-तरफा पूर्णांक श्रेणियों का उपयोग करके संग्रह से अधिक पुनरावृति कर सकते हैं। दस्तावेज से कुछ उदाहरण यहां दिए गए हैं ।

// iterate from index 2 to the end of the array
for name in names[2...] {
    print(name)
}

// iterate from the beginning of the array to index 2
for name in names[...2] {
    print(name)
}

// iterate from the beginning of the array up to but not including index 2
for name in names[..<2] {
    print(name)
}

// the range from negative infinity to 5. You can't iterate forward
// over this because the starting point in unknown.
let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true

// You can iterate over this but it will be an infinate loop 
// so you have to break out at some point.
let range = 5...

तार

यह स्ट्रिंग रेंज के साथ भी काम करता है। यदि आप एक सीमा के साथ str.startIndexया str.endIndexएक छोर पर बना रहे हैं , तो आप इसे छोड़ सकते हैं। संकलक इसे अनुमान लगाएगा।

दिया हुआ

var str = "Hello, playground"
let index = str.index(str.startIndex, offsetBy: 5)

let myRange = ..<index    // Hello

आप इंडेक्स से str.endIndex पर जाकर उपयोग कर सकते हैं ...

var str = "Hello, playground"
let index = str.index(str.endIndex, offsetBy: -10)
let myRange = index...        // playground

यह सभी देखें:

टिप्पणियाँ

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

आगे के अध्ययन


मेरी टिप्पणी "NSRange के साथ समस्या" उपधारा से संबंधित है। NSStringआंतरिक रूप से अपने पात्रों को UTF-16 एन्कोडिंग में संग्रहीत करता है। एक पूर्ण यूनिकोड स्केलर 21-बिट है। ग्रिनिंग फेस कैरेक्टर ( U+1F600) को 16-बिट कोड यूनिट में संग्रहित नहीं किया जा सकता है, इसलिए यह 2. NSRangeबिट कोड यूनिट्स के आधार पर 2. काउंट्स में फैला हुआ है । इस उदाहरण में, 3 कोड इकाइयां केवल 2 वर्णों का प्रतिनिधित्व करने के लिए होती हैं
कोड अलग

25

Xcode 8 बीटा 2 • स्विफ्ट 3

let myString = "Hello World"
let myRange = myString.startIndex..<myString.index(myString.startIndex, offsetBy: 5)
let mySubString = myString.substring(with: myRange)   // Hello

Xcode 7 • स्विफ्ट 2.0

let myString = "Hello World"
let myRange = Range<String.Index>(start: myString.startIndex, end: myString.startIndex.advancedBy(5))

let mySubString = myString.substringWithRange(myRange)   // Hello

या केवल

let myString = "Hello World"
let myRange = myString.startIndex..<myString.startIndex.advancedBy(5)
let mySubString = myString.substringWithRange(myRange)   // Hello


2

इस तरह का उपयोग करें

var start = str.startIndex // Start at the string's start index
var end = advance(str.startIndex, 5) // Take start index and advance 5 characters forward
var range: Range<String.Index> = Range<String.Index>(start: start,end: end)

let firstFiveDigit =  str.substringWithRange(range)

print(firstFiveDigit)

आउटपुट: नमस्कार


मुझे लगता है कि उनके पास "रेंज" डेटाटाइप है। तो मैं इसका उपयोग कैसे कर सकता हूं?
विचाई

@vichhai क्या आप और अधिक विस्तृत कर सकते हैं जहाँ आप उपयोग करना चाहते हैं?
धर्मबीर सिंह

जैसे उद्देश्य c: NSRange रेंज;
विचाई

1

मुझे यह आश्चर्यजनक लगता है कि, स्विफ्ट 4 में भी, इंट का उपयोग करके स्ट्रिंग रेंज को व्यक्त करने का कोई सरल देशी तरीका नहीं है। एकमात्र स्ट्रिंग विधियाँ जो आपको एक Int सप्लाई करती हैं जैसे कि रेंज द्वारा एक सबरिंग प्राप्त करने का एक तरीका है prefixऔर suffix

कुछ रूपांतरण उपयोगिताओं को हाथ में लेना उपयोगी है, ताकि हम स्ट्रिंग की बात करते समय NSRange की तरह बात कर सकें। यहां एक उपयोगिता है जो NSRange की तरह ही एक स्थान और लंबाई लेता है, और एक रिटर्न देता है Range<String.Index>:

func range(_ start:Int, _ length:Int) -> Range<String.Index> {
    let i = self.index(start >= 0 ? self.startIndex : self.endIndex,
        offsetBy: start)
    let j = self.index(i, offsetBy: length)
    return i..<j
}

उदाहरण के लिए, "hello".range(0,1)"है Range<String.Index>का पहला वर्ण को गले लगाने "hello"। एक बोनस के रूप में, मैं नकारात्मक स्थान की अनुमति दी है: "hello".range(-1,1)"है Range<String.Index>का अंतिम वर्ण को गले लगाने "hello"

यह Range<String.Index>एक NSRange में परिवर्तित करने के लिए भी उपयोगी है , उन क्षणों के लिए जब आपको कोको से बात करनी है (उदाहरण के लिए, NSAttributedString विशेषता श्रेणियों से निपटने में)। स्विफ्ट 4 ऐसा करने का मूल तरीका प्रदान करता है:

let nsrange = NSRange(range, in:s) // where s is the string

इस प्रकार हम एक और उपयोगिता लिख ​​सकते हैं जहाँ हम सीधे स्ट्रिंग लोकेशन और लंबाई से NSRange तक जाते हैं:

extension String {
    func nsRange(_ start:Int, _ length:Int) -> NSRange {
        return NSRange(self.range(start,length), in:self)
    }
}

1

अगर कोई NSRange ऑब्जेक्ट बनाना चाहते हैं, तो बना सकते हैं:

let range: NSRange = NSRange.init(location: 0, length: 5)

यह स्थिति 0 और लंबाई 5 के साथ सीमा बनाएगा


0

मैंने निम्नलिखित एक्सटेंशन बनाया:

extension String {
    func substring(from from:Int, to:Int) -> String? {
        if from<to && from>=0 && to<self.characters.count {
            let rng = self.startIndex.advancedBy(from)..<self.startIndex.advancedBy(to)
            return self.substringWithRange(rng)
        } else {
            return nil
        }
    }
}

उपयोग का उदाहरण:

print("abcde".substring(from: 1, to: 10)) //nil
print("abcde".substring(from: 2, to: 4))  //Optional("cd")
print("abcde".substring(from: 1, to: 0))  //nil
print("abcde".substring(from: 1, to: 1))  //nil
print("abcde".substring(from: -1, to: 1)) //nil

0

आप इस तरह का उपयोग कर सकते हैं

let nsRange = NSRange(location: someInt, length: someInt)

जैसे की

let myNSString = bigTOTPCode as NSString //12345678
let firstDigit = myNSString.substringWithRange(NSRange(location: 0, length: 1)) //1
let secondDigit = myNSString.substringWithRange(NSRange(location: 1, length: 1)) //2
let thirdDigit = myNSString.substringWithRange(NSRange(location: 2, length: 4)) //3456

0

मैं यह करना चाहता हूँ:

print("Hello"[1...3])
// out: Error

लेकिन दुर्भाग्य से, मैं अपनी खुद की एक उप-प्रलेख नहीं लिख सकता, क्योंकि शिथिल व्यक्ति नाम स्थान लेता है।

हम हालांकि यह कर सकते हैं:

print("Hello"[range: 1...3])
// out: ell 

बस इसे अपने प्रोजेक्ट में जोड़ें:

extension String {
    subscript(range: ClosedRange<Int>) -> String {
        get {
            let start = String.Index(utf16Offset: range.lowerBound, in: self)
            let end = String.Index(utf16Offset: range.upperBound, in: self)
            return String(self[start...end])
        }
    }
}

0
func replace(input: String, start: Int,lenght: Int, newChar: Character) -> String {
    var chars = Array(input.characters)

    for i in start...lenght {
        guard i < input.characters.count else{
            break
        }
        chars[i] = newChar
    }
    return String(chars)
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.