Есть ли способ выйти из функции сокращения массива в Swift?
Есть ли способ сделать что-то похожее на break
из цикла for
, но в функции массива reduce()
?
например. У меня есть массив:
var flags = [false, false, true, false, false, true, false]
... и мне нужно получить кумулятивный ||
на них. С помощью цикла for
возможно следующее:
var resultByFor = false
for flag in flags {
if flag {
resultByFor = true
break
}
}
... т.е. в тот момент, когда мы получаем наш первый true
, нет необходимости заканчивать цикл, так как результат будет true
в любом случае.
С reduce()
следующее выглядит довольно аккуратно и аккуратно:
var resultByReduce = flags.reduce(false) { $0 || $1 }
Однако с массивом, приведенным в примере, тело цикла for
будет выполняться только 3 раза, а закрытие функции reduce()
будет запускаться полностью 7 раз.
Есть ли способ сделать reduce()
для спасения на третьей итерации (как это можно сделать в цикле for
)?
[UPD]
Я упростил вопрос. Первоначальная проблема была больше такой:
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)
}
... т.е. у меня есть массив объектов, и я хочу знать, есть ли хотя бы один из них, который имеет определенный метод, оценивающий true
.
Ответы
Ответ 1
Как и другие, вы можете использовать contains
для этой цели:
var flags = [false, false, true, false, false, true, false]
contains(flags,true) //--> true
Другой вариант - использовать find
для поиска первого экземпляра того, что вы ищете, в этом случае 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)
Ответ 2
Он не доступен из коробки в стандартной библиотеке Swift, но вы можете это сделать. В мой пост в блоге Я описал свое предлагаемое решение. В вашем случае это будет выглядеть на стороне вызова:
flags.reduce(false, { $0 || $1 }, until: { $0 })
Ответ 3
Попробуйте этот фрагмент кода:
extension Array {
var hasTrue:Bool {
for (idx, objectToCompare) in enumerate(self) {
if let to = objectToCompare as? Bool { if to { return true } }
}
return false
}
}
var flags:[Bool] = [false, false, true, false, false, true, false]
flags.hasTrue
Ответ 4
Как предложил Эрик и Фогмейстер, следующее трюк:
// The closure of contains() will be triggered 3 times
var resultByContains = contains(numbers) {
$0.isWholeMultiplesOf(2)
}