let s = "www.stackoverflow.com"
s.substringWithRange(0..<s.lastIndexOf("."))
Here are the extensions I use:
import Foundation
extension String {
var length: Int {
get {
return countElements(self)
}
}
func indexOf(target: String) -> Int {
var range = self.rangeOfString(target)
if let range = range {
return distance(self.startIndex, range.startIndex)
} else {
return -1
}
}
func indexOf(target: String, startIndex: Int) -> Int {
var startRange = advance(self.startIndex, startIndex)
var range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: Range<String.Index>(start: startRange, end: self.endIndex))
if let range = range {
return distance(self.startIndex, range.startIndex)
} else {
return -1
}
}
func lastIndexOf(target: String) -> Int {
var index = -1
var stepIndex = self.indexOf(target)
while stepIndex > -1 {
index = stepIndex
if stepIndex + target.length < self.length {
stepIndex = indexOf(target, startIndex: stepIndex + target.length)
} else {
stepIndex = -1
}
}
return index
}
func substringWithRange(range:Range<Int>) -> String {
let start = advance(self.startIndex, range.startIndex)
let end = advance(self.startIndex, range.endIndex)
return self.substringWithRange(start..<end)
}
}
var string1 = "www.stackoverflow.com"
var index1 = advance(string1.endIndex, -4)
var substring1 = string1.substringToIndex(index1)
从后面开始找绳子
使用 rangeOfString并将 options设置为 .BackwardsSearch
var string2 = "www.stackoverflow.com"
var index2 = string2.rangeOfString(".", options: .BackwardsSearch)?.startIndex
var substring2 = string2.substringToIndex(index2!)
没有延期,完全是斯威夫特的风格
Swift 2.0
advance现在是 Index的一部分,叫做 advancedBy。你可以这样做:
var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)
Swift 3.0
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)
var substring3 = index2.map(string2.substring(to:))
Swift 4
Swift 3版本仍然有效,但是现在你可以使用带有索引范围的下标:
let string1 = "www.stackoverflow.com"
let index1 = string1.index(string1.endIndex, offsetBy: -4)
let substring1 = string1[..<index1]
第二种方法保持不变:
let string2 = "www.stackoverflow.com"
let index2 = string2.range(of: ".", options: .backwards)?.lowerBound
let substring3 = index2.map(string2.substring(to:))
/// Returns the last index where `value` appears in `domain` or `nil` if
/// `value` is not found.
///
/// Complexity: O(\ `countElements(domain)`\ )
func findLast<C: CollectionType where C.Generator.Element: Equatable>(domain: C, value: C.Generator.Element) -> C.Index? {
var last:C.Index? = nil
for i in domain.startIndex..<domain.endIndex {
if domain[i] == value {
last = i
}
}
return last
}
let str = "www.stackexchange.com"
let substring = map(findLast(str, ".")) { str[str.startIndex ..< $0] } // as String?
// if "." is found, substring has some, otherwise `nil`
ADDED:
也许,BidirectionalIndexType专用版的 findLast更快:
func findLast<C: CollectionType where C.Generator.Element: Equatable, C.Index: BidirectionalIndexType>(domain: C, value: C.Generator.Element) -> C.Index? {
for i in lazy(domain.startIndex ..< domain.endIndex).reverse() {
if domain[i] == value {
return i
}
}
return nil
}
是否希望获取字符串的子字符串从开始索引到其中一个字符的最后一个索引?如果是,您可以选择以下 Swift 2.0 + 方法之一。
Methods that require Foundation
Get a substring that includes the last index of a character:
import Foundation
let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
print(string.substringToIndex(rangeOfIndex.endIndex))
}
// prints "www.stackoverflow."
获取一个不包含字符最后索引的子字符串:
import Foundation
let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
print(string.substringToIndex(rangeOfIndex.startIndex))
}
// prints "www.stackoverflow"
let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
print(string[string.startIndex ..< reverseIndex.base])
}
// prints "www.stackoverflow."
获取一个不包含字符最后索引的子字符串:
let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
print(string[string.startIndex ..< reverseIndex.base.advancedBy(-1)])
}
// prints "www.stackoverflow"
let s = "www.stackoverflow.com"
let start = s.startIndex
let end = s.index(s.endIndex, offsetBy: -4)
let substring = s[start..<end] // www.stackoverflow
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)
}
}
Since advancedBy(Int) is gone since Swift 3 use String's method index(String.Index, Int). Check out this String extension with substring and friends:
public extension String {
//right is the first encountered string after left
func between(_ left: String, _ right: String) -> String? {
guard let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
, leftRange.upperBound <= rightRange.lowerBound
else { return nil }
let sub = self.substring(from: leftRange.upperBound)
let closestToLeftRange = sub.range(of: right)!
return sub.substring(to: closestToLeftRange.lowerBound)
}
var length: Int {
get {
return self.characters.count
}
}
func substring(to : Int) -> String {
let toIndex = self.index(self.startIndex, offsetBy: to)
return self.substring(to: toIndex)
}
func substring(from : Int) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: from)
return self.substring(from: fromIndex)
}
func substring(_ r: Range<Int>) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
return self.substring(with: Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex)))
}
func character(_ at: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: at)]
}
func lastIndexOfCharacter(_ c: Character) -> Int? {
guard let index = range(of: String(c), options: .backwards)?.lowerBound else
{ return nil }
return distance(from: startIndex, to: index)
}
}
更新了 Swift 5的扩展
public extension String {
//right is the first encountered string after left
func between(_ left: String, _ right: String) -> String? {
guard
let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
, leftRange.upperBound <= rightRange.lowerBound
else { return nil }
let sub = self[leftRange.upperBound...]
let closestToLeftRange = sub.range(of: right)!
return String(sub[..<closestToLeftRange.lowerBound])
}
var length: Int {
get {
return self.count
}
}
func substring(to : Int) -> String {
let toIndex = self.index(self.startIndex, offsetBy: to)
return String(self[...toIndex])
}
func substring(from : Int) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: from)
return String(self[fromIndex...])
}
func substring(_ r: Range<Int>) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
let indexRange = Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex))
return String(self[indexRange])
}
func character(_ at: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: at)]
}
func lastIndexOfCharacter(_ c: Character) -> Int? {
guard let index = range(of: String(c), options: .backwards)?.lowerBound else
{ return nil }
return distance(from: startIndex, to: index)
}
}
用法:
let text = "www.stackoverflow.com"
let at = text.character(3) // .
let range = text.substring(0..<3) // www
let from = text.substring(from: 4) // stackoverflow.com
let to = text.substring(to: 16) // www.stackoverflow
let between = text.between(".", ".") // stackoverflow
let substringToLastIndexOfChar = text.lastIndexOfCharacter(".") // 17
extension String {
/// the length of the string
var length: Int {
return self.characters.count
}
/// Get substring, e.g. "ABCDE".substring(index: 2, length: 3) -> "CDE"
///
/// - parameter index: the start index
/// - parameter length: the length of the substring
///
/// - returns: the substring
public func substring(index: Int, length: Int) -> String {
if self.length <= index {
return ""
}
let leftIndex = self.index(self.startIndex, offsetBy: index)
if self.length <= index + length {
return self.substring(from: leftIndex)
}
let rightIndex = self.index(self.endIndex, offsetBy: -(self.length - index - length))
return self.substring(with: leftIndex..<rightIndex)
}
/// Get substring, e.g. -> "ABCDE".substring(left: 0, right: 2) -> "ABC"
///
/// - parameter left: the start index
/// - parameter right: the end index
///
/// - returns: the substring
public func substring(left: Int, right: Int) -> String {
if length <= left {
return ""
}
let leftIndex = self.index(self.startIndex, offsetBy: left)
if length <= right {
return self.substring(from: leftIndex)
}
else {
let rightIndex = self.index(self.endIndex, offsetBy: -self.length + right + 1)
return self.substring(with: leftIndex..<rightIndex)
}
}
}
let string = "www.stackoverflow.com"
let first3Characters = String(string.characters.prefix(3)) // www
let lastCharacters = string.characters.dropFirst(4) // stackoverflow.com (it would be a collection)
//or by index
let indexOfFouthCharacter = olNumber.index(olNumber.startIndex, offsetBy: 4)
let first3Characters = olNumber.substring(to: indexOfFouthCharacter) // www
let lastCharacters = olNumber.substring(from: indexOfFouthCharacter) // .stackoverflow.com
extension String {
// start and end is included
func intBasedSubstring(_ start: Int, _ end: Int) -> String {
let endOffset: Int = -(count - end - 1)
let startIdx = self.index(startIndex, offsetBy: start)
let endIdx = self.index(endIndex, offsetBy: endOffset)
return String(self[startIdx..<endIdx])
}
}
var myString = "abcde"
var subString = myString[2,4] // The result will be "cde"
extension String {
subscript(startIndex: Int, endIndex: Int) -> String {
let start = self.index(self.startIndex, offsetBy: startIndex)
let end = self.index(self.startIndex, offsetBy: endIndex)
let range = start...end
return String(self[range])
}
}