[英]How to use firstIndex in Switft to find all results
我試圖將一個字符串拆分為一個字母數組,但將一些字母放在一起。 (例如,我試圖將它們分成發音組)。 因此,例如,所有“sh”組合將是數組中的一個值,而不是兩個。
使用 firstIndex 在我知道其中包含“sh”的數組中很容易找到“s”。 但是我如何獲得不僅僅是數組的第一個或最后一個索引?
Swift 文檔包括此示例:
let students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
if let i = students.firstIndex(where: { $0.hasPrefix("A") }) {
print("\(students[i]) starts with 'A'!")
}
// Prints "Abena starts with 'A'!"
我如何同時獲得 Abena 和 Akosua(以及其他人,如果還有更多?)
這是我的代碼,它完成了我想要的一些事情(請原諒相當蹩腳的錯誤捕獲)
let message = "she sells seashells"
var letterArray = message.map { String($0)}
var error = false
while error == false {
if message.contains("sh") {
guard let locate1 = letterArray.firstIndex(of: "s") else{
error = true
break }
let locate2 = locate1 + 1
//since it keeps finding an s it doesn't know how to move on to rest of string and we get an infinite loop
if letterArray[locate2] == "h"{
letterArray.insert("sh", at: locate1)
letterArray.remove (at: locate1 + 1)
letterArray.remove (at: locate2)}}
else { error = true }}
print (message, letterArray)
而不是第一次使用過濾器,您將同時獲得 Abena 和 Akosua(以及其他人,如果有更多?)
extension Array where Element: Equatable {
func allIndexes(of element: Element) -> [Int] {
return self.enumerated().filter({ element == $0.element }).map({ $0.offset })
}
}
然后你可以打電話
letterArray.allIndexes(of: "s") // [0, 4, 8, 10, 13, 18]
您可以過濾集合索引:
let students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
let indices = students.indices.filter({students[$0].hasPrefix("A")})
print(indices) // "[1, 4]\n"
您還可以創建自己的帶有謂詞的索引方法:
extension Collection {
func indices(where predicate: @escaping (Element) throws -> Bool) rethrows -> [Index] {
try indices.filter { try predicate(self[$0]) }
}
}
用法:
let indices = students.indices { $0.hasPrefix("A") }
print(indices) // "[1, 4]\n"
或indices(of:)
,其中集合元素是Equatable
:
extension Collection where Element: Equatable {
func indices(of element: Element) -> [Index] {
indices.filter { self[$0] == element }
}
}
用法:
let message = "she sells seashells"
let indices = message.indices(of: "s")
print(indices)
注意:如果您需要在字符串中查找 substring 的所有范圍,您可以查看這篇文章。
玩得開心!
["Kofi", "Abena", "Peter", "Kweku", "Akosua"].forEach {
if $0.hasPrefix("A") {
print("\($0) starts with 'A'!")
}
}
如果你真的想使用firstIndex
方法,這里有一個 recursive(:) 實現,只是為了好玩:D
extension Collection where Element: Equatable {
/// Returns the indices of an element from the specified index to the end of the collection.
func indices(of element: Element, fromIndex: Index? = nil) -> [Index] {
let subsequence = suffix(from: fromIndex ?? startIndex)
if let elementIndex = subsequence.firstIndex(of: element) {
return [elementIndex] + indices(of: element, fromIndex: index(elementIndex, offsetBy: 1))
}
return []
}
}
給定集合中element
的n
實例,function 將被調用n+1
次(包括第一次調用)。
看復雜度, suffix(from:)
是 O(1), firstIndex(of:)
是 O(n)。 假設firstIndex
一旦遇到第一個匹配就終止,任何遞歸都只是從我們離開的地方開始。 因此, indices(of:fromIndex:)
是 O(n),與使用filter
一樣好。 可悲的是,這個 function 不是尾遞歸的......盡管我們可以通過保持運行總數來改變它。
[也許我會再做一次。]
遞歸很有趣,但您可能應該使用 Leo Dabus 的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.