簡體   English   中英

如何在 Switft 中使用 firstIndex 查找所有結果

[英]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 []
    }

}

遞歸

給定集合中elementn實例,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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM