I want to learn the best/simplest way to turn a string into another string but with only a subset, starting at the beginning and going to the last index of a character.
I've extended String with two substring methods. You can call substring with a from/to range or from/length like so:
var bcd = "abcdef".substring(1,to:3)
var cde = "abcdef".substring(2,to:-2)
var cde = "abcdef".substring(2,length:3)
extension String {
public func substring(from:Int = 0, var to:Int = -1) -> String {
if to < 0 {
to = self.length + to
}
return self.substringWithRange(Range<String.Index>(
start:self.startIndex.advancedBy(from),
end:self.startIndex.advancedBy(to+1)))
}
public func substring(from:Int = 0, length:Int) -> String {
return self.substringWithRange(Range<String.Index>(
start:self.startIndex.advancedBy(from),
end:self.startIndex.advancedBy(from+length)))
}
}
For Swift 2.0, it's like this:
var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)
I would do it using a subscript (s[start..<end]
):
let s = "www.stackoverflow.com"
let start = s.startIndex
let end = s.index(s.endIndex, offsetBy: -4)
let substring = s[start..<end] // www.stackoverflow
Swift 2.0 The code below is tested on XCode 7.2 . Please refer to the attached screenshot at the bottom
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var mainText = "http://stackoverflow.com"
var range = Range(start: mainText.startIndex.advancedBy(7), end: mainText.startIndex.advancedBy(24))
var subText = mainText.substringWithRange(range)
//OR Else use below for LAST INDEX
range = Range(start: mainText.startIndex.advancedBy(7), end: mainText.endIndex)
subText = mainText.substringWithRange(range)
}
}
The best way is to use substringToIndex
combined to the endIndex
property and the advance
global function.
var string1 = "www.stackoverflow.com"
var index1 = advance(string1.endIndex, -4)
var substring1 = string1.substringToIndex(index1)
Use rangeOfString
and set options
to .BackwardsSearch
var string2 = "www.stackoverflow.com"
var index2 = string2.rangeOfString(".", options: .BackwardsSearch)?.startIndex
var substring2 = string2.substringToIndex(index2!)
No extensions, pure idiomatic Swift
advance
is now a part of Index
and is called advancedBy
. You do it like:
var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)
You can't call advancedBy
on a String
because it has variable size elements. You have to use index(_, offsetBy:)
.
var string1 = "www.stackoverflow.com"
var index1 = string1.index(string1.endIndex, offsetBy: -4)
var substring1 = string1.substring(to: index1)
A lot of things have been renamed. The cases are written in camelCase, startIndex
became lowerBound
.
var string2 = "www.stackoverflow.com"
var index2 = string2.range(of: ".", options: .backwards)?.lowerBound
var substring2 = string2.substring(to: index2!)
Also, I wouldn't recommend force unwrapping index2
. You can use optional binding or map
. Personally, I prefer using map
:
var substring3 = index2.map(string2.substring(to:))
The Swift 3 version is still valid but now you can now use subscripts with indexes ranges:
let string1 = "www.stackoverflow.com"
let index1 = string1.index(string1.endIndex, offsetBy: -4)
let substring1 = string1[..<index1]
The second approach remains unchanged:
let string2 = "www.stackoverflow.com"
let index2 = string2.range(of: ".", options: .backwards)?.lowerBound
let substring3 = index2.map(string2.substring(to:))
I've modified andrewz' post to make it compatible with Swift 2.0 (and maybe Swift 3.0). In my humble opinion, this extension is easier to understand and similar to what is available in other languages (like PHP).
extension String {
func length() -> Int {
return self.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
}
func substring(from:Int = 0, to:Int = -1) -> String {
var nto=to
if nto < 0 {
nto = self.length() + nto
}
return self.substringWithRange(Range<String.Index>(
start:self.startIndex.advancedBy(from),
end:self.startIndex.advancedBy(nto+1)))
}
func substring(from:Int = 0, length:Int) -> String {
return self.substringWithRange(Range<String.Index>(
start:self.startIndex.advancedBy(from),
end:self.startIndex.advancedBy(from+length)))
}
}