Swift: 获取字符串中某个单词的开始和结束字符的索引

Swift: Get an index of beginning and ending character of a word in a String

一个字符串:

"jim@domain.com, bill@domain.com, chad@domain.com, tom@domain.com"

通过手势识别器,我能够获取用户点击的字符(很乐意提供代码,但目前看不出相关性)。

假设用户在 "chad@domain.com" 中点击了 o 并且字符 index39

给定 39 oindex,我想获取 c 的字符串起始索引,其中 "chad@domain.com" 开始,结束index for m from "com" where "chad@domain.com" ends.

换句话说,给定 Stringcharacterindex,我需要在 leftright 就在我们在左边的 String 和右边的 comma 中遇到 space 之前。

已尝试,但这仅提供字符串中的最后一个单词:

if let range = text.range(of: " ", options: .backwards) {
  let suffix = String(text.suffix(from: range.upperBound)) 
  print(suffix) // tom@domain.com
}

我不知道从这里到哪里去?

不同的方法:

您有字符串和 Int 索引

let string = "jim@domain.com, bill@domain.com, chad@domain.com, tom@domain.com"
let characterIndex = 39

Int

得到 String.Index
let stringIndex = string.index(string.startIndex, offsetBy: characterIndex)

将字符串转换为地址数组

let addresses = string.components(separatedBy: ", ")

将地址映射到字符串中的范围 (Range<String.Index>)

let ranges = addresses.map{string.range(of: [=13=])!}

获取包含stringIndex

的范围的(Int)索引
if let index = ranges.index(where: {[=14=].contains(stringIndex)}) {

获取对应地址

let address = addresses[index] }

一种方法是将原始字符串拆分为“,”,然后使用简单的数学运算在数组的哪个元素中找到给定位置 (39) 存在,并从那里获得正确的字符串或索引前一个 space 和下一个逗号取决于您的最终目标。

您可以对给定字符串的两个片段调用 range(of:)text[..<index] 是给定字符位置之前的文本, text[index...] 是从给定位置开始的文本。

示例:

let text = "jim@domain.com, bill@domain.com, chad@domain.com, tom@domain.com"
let index = text.index(text.startIndex, offsetBy: 39)

// Search the space before the given position:
let start = text[..<index].range(of: " ", options: .backwards)?.upperBound ?? text.startIndex

// Search the comma after the given position: 
let end = text[index...].range(of: ",")?.lowerBound ?? text.endIndex

print(text[start..<end]) // chad@domain.com

两个range(of:)调用return nil如果没有space(或逗号)有 被发现。在这种情况下,使用 nil-coalescing 运算符 ?? 获取开始(或结束)索引。

(请注意,这是有效的,因为 Substrings 共享一个公共索引 及其原始字符串。)


另一种方法是使用 "data detector", 因此 URL 检测不依赖于某些分隔符。

示例(比较 How to detect a URL in a String using NSDataDetector):

let text = "jim@domain.com, bill@domain.com, chad@domain.com, tom@domain.com"
let index = text.index(text.startIndex, offsetBy: 39)

let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let matches = detector.matches(in: text, range: NSRange(location: 0, length: text.utf16.count))

for match in matches {
    if let range = Range(match.range, in: text), range.contains(index) {
        print(text[range])
    }
}