Есть ли способ оторваться от функции уменьшения массива в 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()
выручить и на 3-й итерации (так же, как это можно сделать в 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
,
4 ответа
Как и предполагали другие, вы можете использовать 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)
Это не доступно из коробки в стандартной библиотеке Swift, но вы можете сделать это. В своем блоге я описал предложенное мной решение. В вашем случае это будет выглядеть так на стороне вызова:
flags.reduce(false, { $0 || $1 }, until: { $0 })
Попробуйте этот кусок кода:
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
Современный способ решения вашей «первоначальной проблемы»
[3, 5, 6, 7, 2, 3, 8].contains {
$0.isMultiple(of: 2)
}
Для повторных замыканий нет, как и нет
break
допускается в основном теле функции. Чтобы имитировать это, вам нужно сбросить ошибку.
for number in numbers {
guard !number.isMultiple(of: 2) else {
break
}
print(number)
}
try? numbers.forEach {
guard !$0.isMultiple(of: 2) else {
struct Error: Swift.Error { }
throw Error()
}
print($0)
}