I'm aware of Swift's higher-order functions like Map, Filter, Reduce and FlatMap, but I'm not aware of any like 'All' or 'Any' which return a boolean that short-circuit on a positive test while enumerating the results.
For instance, consider you having a collection of 10,000 objects, each with a property called isFulfilled
and you want to see if any in that collection have isFulfilled
set to false. In C#, you could use myObjects.Any(obj -> !obj.isFulfilled)
and when that condition was hit, it would short-circuit the rest of the enumeration and immediately return true
.
Is there any such thing in Swift?
Sequence
(and in particular Collection
and Array
) has a (short-circuiting) contains(where:)
method taking a boolean predicate as argument. For example,
if array.contains(where: { $0 % 2 == 0 })
checks if the array contains any even number.
There is no "all" method, but you can use contains()
as well
by negating both the predicate and the result. For example,
if !array.contains(where: { $0 % 2 != 0 })
checks if all numbers in the array are even. Of course you can define a custom extension method:
extension Sequence {
func allSatisfy(_ predicate: (Iterator.Element) -> Bool) -> Bool {
return !contains(where: { !predicate($0) } )
}
}
If you want to allow "throwing" predicates in the same way as the
contains
method then it would be defined as
extension Sequence {
func allSatisfy(_ predicate: (Iterator.Element) throws -> Bool) rethrows -> Bool {
return try !contains(where: { try !predicate($0) } )
}
}
Update: As James Shapiro correctly noticed, an allSatisfy
method has been added to the Sequence
type in Swift 4.2 (currently in beta), see
(Requires a recent 4.2 developer snapshot.)