উত্তর:
সুইফট 4-র জন্য আপডেট হয়েছে
সুইফট রেঞ্জগুলি আরও জটিল NSRange
এবং সুইফট ৩ এ এগুলি সহজতর কিছু পায় নি যদি আপনি এই জটিলতার কিছুটির পিছনে যুক্তি বোঝার চেষ্টা করতে চান তবে এটি এবং এটি পড়ুন । এগুলি কীভাবে তৈরি করা যায় এবং আপনি কখন সেগুলি ব্যবহার করতে পারেন তা আমি আপনাকে কেবল দেখাব।
a...b
এই ব্যাপ্তি অপারেটর একটি সুইফট পরিসর তৈরি করে যার মধ্যে উপাদান a
এবং উপাদান উভয়ই অন্তর্ভুক্ত b
থাকে, এমনকি যদি b
কোনও ধরণের (পছন্দ মতো Int.max
) সর্বাধিক সম্ভাব্য মান হয় । দুটি ধরণের বন্ধ রেঞ্জ রয়েছে: ClosedRange
এবংCountableClosedRange
।
ClosedRange
সুইফ্টের সমস্ত ব্যাপ্তির উপাদানগুলি তুলনামূলক (যেমন, তারা তুলনীয় প্রোটোকলের সাথে সঙ্গতিপূর্ণ)। এটি আপনাকে সংগ্রহ থেকে রেঞ্জের উপাদানগুলিকে অ্যাক্সেস করতে দেয়। এখানে একটি উদাহরণ:
let myRange: ClosedRange = 1...3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]
তবে, একটি ClosedRange
গণনাযোগ্য নয় (যেমন, এটি সিকোয়েন্স প্রোটোকলের সাথে সম্মতি দেয় না)। এর অর্থ আপনি for
লুপ দিয়ে উপাদানগুলির উপর পুনরাবৃত্তি করতে পারবেন না । যে আপনি প্রয়োজন জন্য CountableClosedRange
।
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
।
Range
হিসাবে ClosedRange
, আপনি একটি দিয়ে সংগ্রহের উপাদানগুলি অ্যাক্সেস করতে পারেন Range
। উদাহরণ:
let myRange: Range = 1..<3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]
আবার, যদিও আপনি a এর উপর পুনরাবৃত্তি করতে পারবেন না Range
কোনওটি কারণ এটি কেবল তুলনীয়, স্ট্রাইড নয়।
CountableRange
এ 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
সময়ে সময়ে সুইফট ব্যবহার করতে পারেন ( যেমন বিশিষ্ট স্ট্রিংগুলি তৈরি করার সময় ), সুতরাং এটি কীভাবে তৈরি করা যায় তা জানার জন্য সহায়ক।
let myNSRange = NSRange(location: 3, length: 2)
মনে রাখবেন যে এটি অবস্থান এবং দৈর্ঘ্য , সূচক এবং শেষ সূচক নয়। এখানে উদাহরণটি সুইফ্ট পরিসরের সাথে একই রকম 3..<5
। তবে, যেহেতু প্রকারগুলি পৃথক, সেগুলি বিনিময়যোগ্য নয়।
...
এবং ..<
পরিসীমা অপারেটার রেঞ্জ তৈরি করার একটি সাঁটে লেখার উপায়। উদাহরণ স্বরূপ:
let myRange = 1..<3
একই পরিসীমা তৈরির দীর্ঘ হাতের পথ হবে
let myRange = CountableRange<Int>(uncheckedBounds: (lower: 1, upper: 3)) // 1..<3
আপনি দেখতে পাচ্ছেন যে এখানে সূচক টাইপ রয়েছে Int
। String
যদিও এটি কার্যকর হয় না , কারণ স্ট্রিংগুলি অক্ষর দ্বারা তৈরি এবং সমস্ত অক্ষর একই আকার নয়। (পড়ুন এই আরও তথ্যের জন্য।) মত 😀 একটি ইমোজি, উদাহরণস্বরূপ, চিঠি "B" চেয়ে আরও জায়গা লাগে।
এনএসরেঞ্জের সাথে সমস্যা
ইমোজি সহ 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"!?
হাসিখুশি মুখ দুটি ইউটিএফ -16 কোড ইউনিট নেয়, সুতরাং এটি "ডি" অন্তর্ভুক্ত না করার অপ্রত্যাশিত ফলাফল দেয়।
সুইফট সলিউশন
এর কারণে, আপনি যে সুইফট স্ট্রিংগুলি ব্যবহার করেন 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 টি জিনিস কিছুটা সরল করা হয়েছিল। যখনই কোনও ব্যাপ্তির শুরুর বা শেষ পয়েন্টটি অনুমান করা যায়, আপনি এটিকে ছেড়ে দিতে পারেন।
int
সংগ্রহের মাধ্যমে পুনরাবৃত্তি করতে আপনি একতরফা পূর্ণসংখ্যার ব্যাপ্তি ব্যবহার করতে পারেন। এখানে ডকুমেন্টেশন থেকে কিছু উদাহরণ দেওয়া আছে ।
// 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
মন্তব্য
NSString
অভ্যন্তরীণভাবে ইউটিএফ -16 এনকোডিংয়ে এর অক্ষরগুলি সঞ্চয় করে। একটি সম্পূর্ণ ইউনিকোড স্কেলারটি 21-বিট। গ্রিনিং ফেস ক্যারেক্টার ( U+1F600
) একক 16-বিট কোড ইউনিটে সংরক্ষণ করা যায় না, সুতরাং এটি 2 টির মধ্যে ছড়িয়ে আছে NSRange
16 বিট কোড ইউনিটের উপর ভিত্তি করে গণনা। এই উদাহরণস্বরূপ, 3 কোড ইউনিট কেবল 2 টি অক্ষরের প্রতিনিধিত্ব করতে পারে
এক্সকোড 8 বিটা 2 • সুইফট 3
let myString = "Hello World"
let myRange = myString.startIndex..<myString.index(myString.startIndex, offsetBy: 5)
let mySubString = myString.substring(with: myRange) // Hello
এক্সকোড 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
এই মত ব্যবহার করুন
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)
আউটপুট: হ্যালো
আমি অবাক করে দিয়েছি যে, এমনকি সুইফট 4-এ, ইন্ট ব্যবহার করে স্ট্রিং রেঞ্জটি প্রকাশ করার মতো সহজ কোনও নেটিভ উপায় নেই। কেবলমাত্র স্ট্রিং পদ্ধতিগুলি আপনাকে পরিসীমা অনুসারে একটি স্ট্রিংগুলি পাওয়ার উপায় হিসাবে কোনও ইন্টার সরবরাহ করতে দেয় prefix
এবং সেগুলি suffix
।
কিছু রূপান্তর ইউটিলিটি হাতে রাখা দরকারী, যাতে কোনও স্ট্রিংয়ের সাথে কথা বলার সময় আমরা এনএসরেঞ্জের মতো কথা বলতে পারি। এখানে একটি ইউটিলিটি যা 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>
কোনও এনএসআরঞ্জে রূপান্তরিত করাও দরকারী , সেই মুহুর্তগুলির জন্য যখন আপনাকে কোকোয়ের সাথে কথা বলতে হবে (উদাহরণস্বরূপ, এনএস্যাট্রিবিউটেড স্ট্রিং অ্যাট্রিবিউট রেঞ্জগুলি নিয়ে কাজ করার ক্ষেত্রে)। সুইফট 4 এটি করার একটি স্থানীয় উপায় সরবরাহ করে:
let nsrange = NSRange(range, in:s) // where s is the string
আমরা এইভাবে আরও একটি ইউটিলিটি লিখতে পারি যেখানে আমরা স্ট্রিংয়ের অবস্থান এবং দৈর্ঘ্য থেকে সরাসরি এনএসরেঞ্জে যাই:
extension String {
func nsRange(_ start:Int, _ length:Int) -> NSRange {
return NSRange(self.range(start,length), in:self)
}
}
আমি নিম্নলিখিত এক্সটেনশনটি তৈরি করেছি:
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
আপনি এটি ব্যবহার করতে পারেন
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
আমি এটা করতে চাই:
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])
}
}
}
Range<String.Index>
তবে কখনও কখনও এটির সাথে কাজ করা প্রয়োজনNSString
এবংNSRange
তাই আরও কিছু প্রসঙ্গ দরকারী। - তবে স্ট্যাকওভারফ্লো . com/ জিজ্ঞাসাগুলি / ২৪৪০২৮৮৪৮/২ দেখুন ।