使用Swift的字符串中子字符串的索引

Arm*_*let 56 string substring swift

我习惯在JavaScript中这样做:

var domains = "abcde".substring(0, "abcde".indexOf("cd")) // Returns "ab"
Run Code Online (Sandbox Code Playgroud)

Swift没有这个功能,如何做类似的事情?

Leo*_*bus 98

Xcode 9•Swift 4或更高版本

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] {
        var indices: [Index] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...]
                .range(of: string, options: options) {
                indices.append(range.lowerBound)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return indices
    }
    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
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let str = "abcde"
if let index = str.index(of: "cd") {
    let substring = str[..<index]   // ab
    let string = String(substring)
    print(string)  // "ab\n"
}
Run Code Online (Sandbox Code Playgroud)
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}]
Run Code Online (Sandbox Code Playgroud)

不区分大小写的样本

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

正则表达式样本

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"]
Run Code Online (Sandbox Code Playgroud)

  • 这是不对的,因为"ab".indexOf("a")`和`"ab".indexOf("c")`都返回"0". (2认同)
  • **确保你** `import Foundation` **否则这将不起作用。**因为实际上你此时只是使用 NSString 。 (2认同)

Ind*_*ore 39

测试Swift 4.2/4.1/4.0/3.0

使用String[Range<String.Index>]下标,您可以获得子字符串.您需要启动索引和最后一个索引来创建范围,您可以按照以下方式执行此操作

let str = "abcde"
if let range = str.range(of: "cd") {
  let substring = str[..<range.lowerBound] // or str[str.startIndex..<range.lowerBound]
  print(substring)  // Prints ab
}
else {
  print("String not present")
}
Run Code Online (Sandbox Code Playgroud)

如果没有为此运算符定义起始索引..<,则采用起始索引.您也可以使用str[str.startIndex..<range.lowerBound]而不是str[..<range.lowerBound]


Vik*_*tor 23

斯威夫特 5

查找子串的索引

let str = "abcdecd"
if let range: Range<String.Index> = str.range(of: "cd") {
    let index: Int = str.distance(from: str.startIndex, to: range.lowerBound)
    print("index: ", index) //index: 2
}
else {
    print("substring not found")
}
Run Code Online (Sandbox Code Playgroud)

查找字符索引

let str = "abcdecd"
if let firstIndex = str.firstIndex(of: "c") {
    let index = str.distance(from: str.startIndex, to: firstIndex)
    print("index: ", index)   //index: 2
}
else {
    print("symbol not found")
}
Run Code Online (Sandbox Code Playgroud)


Arm*_*let 6

在 Swift 中执行此操作是可能的,但需要更多行,这是一个indexOf()执行预期操作的函数:

func indexOf(source: String, substring: String) -> Int? {
    let maxIndex = source.characters.count - substring.characters.count
    for index in 0...maxIndex {
        let rangeSubstring = source.startIndex.advancedBy(index)..<source.startIndex.advancedBy(index + substring.characters.count)
        if source.substringWithRange(rangeSubstring) == substring {
            return index
        }
    }
    return nil
}

var str = "abcde"
if let indexOfCD = indexOf(str, substring: "cd") {
    let distance = str.startIndex.advancedBy(indexOfCD)
    print(str.substringToIndex(distance)) // Returns "ab"
}
Run Code Online (Sandbox Code Playgroud)

这个函数没有优化,但它可以处理短字符串。

  • 非常令人沮丧的是,他们还没有将它添加到 Swift 库中! (7认同)

Ash*_*aha 6

在Swift 4中:

获取字符串中的字符索引:

let str = "abcdefghabcd"
if let index = str.index(of: "b") {
   print(index) // Index(_compoundOffset: 4, _cache: Swift.String.Index._Cache.character(1))
}
Run Code Online (Sandbox Code Playgroud)

使用Swift 4从String创建SubString(前缀和后缀):

let str : String = "ilike"
for i in 0...str.count {
    let index = str.index(str.startIndex, offsetBy: i) // String.Index
    let prefix = str[..<index] // String.SubSequence
    let suffix = str[index...] // String.SubSequence
    print("prefix \(prefix), suffix : \(suffix)")
}
Run Code Online (Sandbox Code Playgroud)

产量

prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix : 
Run Code Online (Sandbox Code Playgroud)

如果要生成2个索引之间的子字符串,请使用:

let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex
Run Code Online (Sandbox Code Playgroud)


小智 5

雨燕5

   let alphabet = "abcdefghijklmnopqrstuvwxyz"

    var index: Int = 0
    
    if let range: Range<String.Index> = alphabet.range(of: "c") {
         index = alphabet.distance(from: alphabet.startIndex, to: range.lowerBound)
        print("index: ", index) //index: 2
    }
Run Code Online (Sandbox Code Playgroud)