我components(separatedBy:)用來將字串分隔成單詞陣列(使用空格" "作為分隔符)。
let string = "This is a string."
let words = string.components(separatedBy: " ")
print(words) // Result: ["This", "is", "a", "string."]
這很好用,但我也想在父字串中獲取每個單詞的范圍/索引。這是我目前的蠻力嘗試。它有點作業,但是在一些單詞之后有一個額外的空格,我不知道它在應用于其他字串時如何執行。
let string = "This is a string."
let words = string.words(separatedBy: " ")
print(words)
/* Result:
[
Word(range: Range(0..<4), component: "This "),
Word(range: Range(5..<7), component: "is "),
Word(range: Range(8..<9), component: "a "),
Word(range: Range(10..<16), component: "string."),
]
*/
/// ...
struct Word {
var range: Range<Int> /// the component's range in a parent string
var component: String
}
extension String {
func words(separatedBy separator: String) -> [Word] {
var words = [Word]()
var currentWord: Word? /// the current word that the loop pieces together
for stringIndex in indices {
/// get the index as an `Int`
let index = distance(from: startIndex, to: stringIndex)
let letter = String(self[stringIndex])
if var word = currentWord {
word.component.append(letter)
currentWord = word
/// check if the letter is the separator, or if this index is the last one
if letter == separator || stringIndex == indices.last {
word.range = word.range.startIndex..<index
words.append(word)
currentWord = nil
}
} else {
currentWord = Word(range: index..<index 1, component: letter)
}
}
return words
}
}
是否有一個內置函式不僅可以將字串拆分為陣列,還可以回傳范圍?如果沒有,我可以使用一些不那么蠻力的東西嗎?
uj5u.com熱心網友回復:
您可以在范圍內使用列舉子字串并傳遞 byWords 選項:
extension StringProtocol {
var wordsAndRanges: [(word: String,range: Range<Index>)] {
var result: [(word: String, range: Range<Index>)] = []
enumerateSubstrings(in: startIndex..., options: .byWords) { word, range, _, _ in
guard let word = word else { return }
result.append((word, range))
}
return result
}
}
let string = "This is a string."
for (word, range) in string.wordsAndRanges {
print("word:", word)
print("substring:", string[range])
print("range:", range)
}
或者您嘗試使用 Word 結構:
struct Word {
let range: Range<String.Index>
let component: String
}
extension StringProtocol {
var words: [Word] {
var result: [Word] = []
enumerateSubstrings(in: startIndex..., options: .byWords) { word, range, _, _ in
guard let word = word else { return }
result.append(.init(range: range, component: word))
}
return result
}
}
let string = "This is a string."
for word in string.words {
print("word:", word.component)
print("subsequence", string[word.range])
print("range", word.range)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/440611.html
上一篇:UITextField:前導截斷
