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