In a different projects written in Swift I've seen a snippet like that: [1, 2, nil, 3, nil, nil, 4].compactMap { $0 }.filter { $0 > 2 }.
Instead of that I prefer to use this extension:
@afarnham Thank you for your answer !!!
However I need to use this code snippet in more than 10 different places. That's why I want to wrap it into some extension of Array. Is it possible to replace implementation of the compactFilter with your solution?
Sure, you can simply define your own standalone function for this.
func compactFilter<S: Sequence, Element>(
_ values: S,
_ predicate: (Element) throws -> Bool
) rethrows -> [Element]
where S.Element == Element? {
return try values.compactMap { value in
guard let value = value, try predicate(value) else { return nil }
return value
}
}
let a: [Int?] = [1, 2, nil, 3, nil, nil, 4]
compactFilter(a) { $0 > 2 }
// ⟹ [3, 4]
It isn't currently possible to define this as an extension on any Sequence (or Array etc.) holding optional elements -- we'd need parameterized extensions for that:
extension<T> Sequence where Element == Optional<T> { // Not valid Swift (yet?)
func compactFilter(...) {...}
}
However, if you only need it to work with a single concrete type (e.g., [Int?]), this works fine:
extension Array where Element == Int? {
func compactFilter(_ predicate: (Int) throws -> Bool) rethrows -> [Int] {
return try self.compactMap { value in
guard let value = value, try predicate(value) else { return nil }
return value
}
}
}
a.compactFilter { $0 > 2 }
// ⟹ [3, 4]