Ana Ana - 4 years ago 218
Swift Question

Swift function to find first element of collection matching a predicate?

If

xs
is a collection and
pred
is a closure that returns a
Bool
, is there a built-in function that does the following?

xs.filter(pred).first


This gets the first element of a collection matching the predict, or
nil
if there is no match. Not interested in the index, but the element itself.

Answer Source

No there isn't, but you can write one yourself like this:

extension SequenceType {
    func first(@noescape pred: Generator.Element throws -> Bool) rethrows -> Generator.Element? {
        return try filter(pred).first
    }
}

EDIT: This version isn't optimal, since the filter creates a whole new array, even though only the first element would be needed. As noted by Martin R, lazy.filter also doesn't work for. This would be necessary to make it work with lazy:

extension CollectionType {
    func first(pred: Generator.Element -> Bool) -> Generator.Element? {
        return lazy.filter(pred).first
    }
}

Because:

  • @noescape can't be used because @noescape means that the closure cannot escape the current function, which would be possible when passing it to the lazy filter (doesn't evaluate elements until it is asked to -> has to escape the predicate)
  • throws can't be used because the filter is lazy -> errors wouldn't be thrown immediately, but rather when it is used the first time which would be when calling first, but first can't be throwing because it's a property. There are some discussions on making getters (and subscripts) throwing in future versions of Swift.
  • CollectionType has to be used, because only LazyCollectionType has the first property.

So to really make it lazy and have all the @noescape, throws and SequenceType, you'd have to use an imperative approach:

extension SequenceType {
    func first(@noescape pred: Generator.Element throws -> Bool) rethrows -> Generator.Element? {
        for elem in self where try pred(elem) {
            return elem
        }
        return nil
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download