在 Swift 数组中查找第一个元素匹配条件(例如 EKSource)

Find first element matching condition in Swift array (e.g. EKSource)

我想在 Swift 中找到 EKSourceType.Local 类型的第一个 EKSource 和 "single" 行表达式。这是我目前拥有的:

let eventSourceForLocal = 
    eventStore.sources[eventStore.sources.map({ [=11=].sourceType })
        .indexOf(EKSourceType.Local)!]

是否有更好的方法(例如不使用 find 的通用版本映射 and/or)?

indexOf 的一个版本采用谓词闭包 - 使用它来查找第一个本地源的索引(如果存在),然后在 eventStore.sources 上使用该索引:

if let index = eventStore.sources.indexOf({ [=10=].sourceType == .Local }) {
    let eventSourceForLocal = eventStore.sources[index]
}

或者,您可以通过 SequenceType 上的扩展添加通用 find 方法:

extension SequenceType {
    func find(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
        for element in self {
            if try predicate(element) {
                return element
            }
        }
        return nil
    }
}

let eventSourceForLocal = eventStore.sources.find({ [=11=].sourceType == .Local })

(为什么这个还没有?)

我完全不明白你为什么要使用 map。为什么不使用 filter?然后你会得到所有的本地资源,但实际上可能只有一个,或者 none,你可以很容易地通过询问第一个(它将是 nil如果没有的话):

let local = eventStore.sources.filter{[=10=].sourceType == .Local}.first

对于 Swift 3,您需要对上面 Nate 的回答做一些小改动。这是 Swift 3 版本:

public extension Sequence {
    func find(predicate: (Iterator.Element) throws -> Bool) rethrows -> Iterator.Element? {
        for element in self {
            if try predicate(element) {
                return element
            }
        }
        return nil
    }
}

更改:SequenceType > SequenceSelf.Generator.Element > Iterator.Element

或者在 Swift3 中你可以使用:

let local = eventStore.sources.first(where: {[=10=].sourceType == .Local}) 

让我们尝试一些更实用的东西:

let arr = [0,1,2,3]
let result = arr.lazy.map { print(""); return [=10=] }.first(where: { [=10=] == 2 })
print(result) // 3x  then 2

这有什么好看的?
您可以在搜索时访问 element 或 i。而且它很实用。

Swift 4 解决方案还可以处理数组中没有符合条件的元素的情况:

if let firstMatch = yourArray.first{[=10=].id == lookupId} {
  print("found it: \(firstMatch)")
} else {
  print("nothing found :(")
}

Swift 5 如果你想从模型数组中找出然后指定 $0.keyTofound 否则使用 $0

if let index = listArray.firstIndex(where: { [=10=].id == lookupId }) {
     print("Found at \(index)")
} else {
     print("Not found")
 }