我习惯于在JavaScript中这样做:

var domains = "abcde".substring(0, "abcde".indexOf("cd")) // Returns "ab"

Swift 没有这个功能,怎么做类似的事情?

推荐答案

编辑/更新:

Xcode 11.4 • Swift 5.2 or later

import Foundation

extension StringProtocol {
    func index<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.lowerBound
    }
    func endIndex<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.upperBound
    }
    func indices<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Index] {
        ranges(of: string, options: options).map(\.lowerBound)
    }
    func ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>] {
        var result: [Range<Index>] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...]
                .range(of: string, options: options) {
                result.append(range)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return result
    }
}

usage:

let str = "abcde"
if let index = str.index(of: "cd") {
    let substring = str[..<index]   // ab
    let string = String(substring)
    print(string)  // "ab\n"
}

let str = "Hello, playground, playground, playground"
str.index(of: "play")      // 7
str.endIndex(of: "play")   // 11
str.indices(of: "play")    // [7, 19, 31]
str.ranges(of: "play")     // [{lowerBound 7, upperBound 11}, {lowerBound 19, upperBound 23}, {lowerBound 31, upperBound 35}]

不区分大小写的样本

let query = "Play"
let ranges = str.ranges(of: query, options: .caseInsensitive)
let matches = ranges.map { str[$0] }   //
print(matches)  // ["play", "play", "play"]

正则表达式示例

let query = "play"
let escapedQuery = NSRegularExpression.escapedPattern(for: query)
let pattern = "\\b\(escapedQuery)\\w+"  // matches any word that starts with "play" prefix

let ranges = str.ranges(of: pattern, options: .regularExpression)
let matches = ranges.map { str[$0] }

print(matches) //  ["playground", "playground", "playground"]

Swift相关问答推荐

如何为任务扩展的泛型静态函数获得自动类型推理

SwiftUI map 旋转

查找数组中 ** 元素 ** 的属性的最小值和最大值

当计数大于索引时,索引超出范围崩溃

为什么我不能在这个 Swift 间接枚举中返回 self ?

使用序列初始化字符串的时间复杂度是多少?

更改 SwiftUI 中按钮矩阵的填充 colored颜色

协议元类型'SomeProtocol.Type'上无法使用静态成员'currency'

为什么这段Swift读写锁代码会导致死锁?

设备上ScrollView为什么会将内容高度更改为随机值,而在预览上不会? - 优化后的标题:设备上ScrollView内容高度随机变化问题解决

如何在 Swift 中做类型安全的索引?

Swiftui 无法从核心数据中获取数据

如何为等待函数调用添加超时

使用 RxSwift 围绕 async/await 方法创建 Observable

有什么方法可以快速为泛型参数分配默认值?

Swift初始化具有可变ID的重复值数组

符合协议要求委托变量在 ios13 中可用

Swift 5.0 编译器无法导入使用 Swift 4.2.1 编译的模块

在 Swiftui 中是否有一种简单的方法可以通过捏合来放大图像?

Swift 2.0 最低系统版本要求(部署目标)