How do you use String.substringWithRange? (or, how do Ranges work in Swift?)
Swift 2
Simple
let str = "My String"
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)]
//"Strin"
Swift 3
let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)
str[startIndex...endIndex] // "Strin"
str.substring(to: startIndex) // "My "
str.substring(from: startIndex) // "String"
Swift 4
substring(to:)
and substring(from:)
are deprecated in Swift 4
.
String(str[..<startIndex]) // "My "
String(str[startIndex...]) // "String"
String(str[startIndex...endIndex]) // "Strin"
NOTE: @airspeedswift makes some very insightful points on the trade-offs of this approach, particularly the hidden performance impacts. Strings are not simple beasts, and getting to a particular index may take O(n) time, which means a loop that uses a subscript can be O(n^2). You have been warned.
You just need to add a new subscript
function that takes a range and uses advancedBy()
to walk to where you want:
import Foundation
extension String {
subscript (r: Range<Int>) -> String {
get {
let startIndex = self.startIndex.advancedBy(r.startIndex)
let endIndex = startIndex.advancedBy(r.endIndex - r.startIndex)
return self[Range(start: startIndex, end: endIndex)]
}
}
}
var s = "Hello, playground"
println(s[0...5]) // ==> "Hello,"
println(s[0..<5]) // ==> "Hello"
(This should definitely be part of the language. Please dupe rdar://17158813)
For fun, you can also add a +
operator onto the indexes:
func +<T: ForwardIndex>(var index: T, var count: Int) -> T {
for (; count > 0; --count) {
index = index.succ()
}
return index
}
s.substringWithRange(s.startIndex+2 .. s.startIndex+5)
(I don't know yet if this one should be part of the language or not.)
You can use the substringWithRange method. It takes a start and end String.Index.
var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex, end: str.endIndex)) //"Hello, playground"
To change the start and end index, use advancedBy(n).
var str = "Hello, playground"
str.substringWithRange(Range<String.Index>(start: str.startIndex.advancedBy(2), end: str.endIndex.advancedBy(-1))) //"llo, playgroun"
You can also still use the NSString method with NSRange, but you have to make sure you are using an NSString like this:
let myNSString = str as NSString
myNSString.substringWithRange(NSRange(location: 0, length: 3))
Note: as JanX2 mentioned, this second method is not safe with unicode strings.