(1..<10)
returns...
Range = 1..<10
I want to do this:
print("Hello"[1...3])
// out: Error
But unfortunately, I can't write a subscript of my own because the loathed one takes up the name space.
We can do this however:
print("Hello"[range: 1...3])
// out: ell
Just add this to your project:
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])
}
}
}
I find it surprising that, even in Swift 4, there's still no simple native way to express a String range using Int. The only String methods that let you supply an Int as a way of obtaining a substring by range are prefix
and suffix
.
It is useful to have on hand some conversion utilities, so that we can talk like NSRange when speaking to a String. Here's a utility that takes a location and length, just like NSRange, and returns a 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
}
For example, "hello".range(0,1)"
is the Range<String.Index>
embracing the first character of "hello"
. As a bonus, I've allowed negative locations: "hello".range(-1,1)"
is the Range<String.Index>
embracing the last character of "hello"
.
It is useful also to convert a Range<String.Index>
to an NSRange, for those moments when you have to talk to Cocoa (for example, in dealing with NSAttributedString attribute ranges). Swift 4 provides a native way to do that:
let nsrange = NSRange(range, in:s) // where s is the string
We can thus write another utility where we go directly from a String location and length to an NSRange:
extension String {
func nsRange(_ start:Int, _ length:Int) -> NSRange {
return NSRange(self.range(start,length), in:self)
}
}
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)
}
Use like this
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)
Output : Hello
Xcode 8 beta 2 • Swift 3
let myString = "Hello World"
let myRange = myString.startIndex..<myString.index(myString.startIndex, offsetBy: 5)
let mySubString = myString.substring(with: myRange) // Hello
Xcode 7 • Swift 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
or simply
let myString = "Hello World"
let myRange = myString.startIndex..<myString.startIndex.advancedBy(5)
let mySubString = myString.substringWithRange(myRange) // Hello
I created the following extension:
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
}
}
}
example of use:
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
If anyone want to create NSRange object can create as:
let range: NSRange = NSRange.init(location: 0, length: 5)
this will create range with position 0 and length 5
You can use like this
let nsRange = NSRange(location: someInt, length: someInt)
as in
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
Source: Stackoverflow.com