Есть ли способ выйти из функции сокращения массива в 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)
}