Is there a way to do something similar to break
from a for
loop but in array's reduce()
function?
E.g. consider I have an array:
var flags = [false, false, true, false, false, true, false]
... and I need to get a cumulative ||
on them. With a for
loop, the following would be possible:
var resultByFor = false
for flag in flags {
if flag {
resultByFor = true
break
}
}
... i.e. at the moment we get our first true
there is no need to finish the loop as the result will be true
anyway.
With reduce()
, the following looks quite neat and tidy:
var resultByReduce = flags.reduce(false) { $0 || $1 }
However, with the array given in the example, the for
loop body would be executed only 3 times, while reduce()
function closure would get triggered full 7 times.
Is there a way to make reduce()
to bail out on 3rd iteration as well (just like it can be done in for
loop)?
[UPD]
I oversimplified the question. The original problem was more like this:
extension Int {
func isWholeMultiplesOf(base: Int) -> Bool {
return (self % base) == 0
}
}
var numbers = [3, 5, 6, 7, 2, 3, 8]
var resultByFor = false
// The loop body will be triggered only 3 times
for number in numbers {
if number.isWholeMultiplesOf(2) {
resultByFor = true
break
}
}
// The closure of reduce() will be triggered 7 times
var resultByReduce = numbers.reduce(false) {
$0 || $1.isWholeMultiplesOf(2)
}
... i.e. I have an array of objects and I want to know if there is at least one of them that has certain method evaluating to true
.
As others have suggested, you can use contains
for this purpose:
var flags = [false, false, true, false, false, true, false]
contains(flags, true) //--> true
Another option is to use find
to search for the first instance of what you're looking for, in this case true
:
var flags = [false, false, true, false, false, true, false]
find(flags, true) // --> 2, returns nil if not found
let containsTrue = (find(flags, true) != nil)
Edit: Newer versions of Swift expose these functions on the related collection protocols instead of global functions.
var flags = [false, false, true, false, false, true, false]
flags.contains(where: { $0 == true })
flags.contains(true) // if checking for a specific element
let index = flags.firstIndex(where: ${ $0 == true }) // --> 2
It's not available out of the box in the Swift Standard Library, but you can make it. In my blog post I have described my proposed solution. In your case it'll look like this on the call side:
flags.reduce(false, { $0 || $1 }, until: { $0 })
You can give it a try in that Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With