有没有办法在 Swift 中中断数组的 reduce 函数?

Is there a way to break from an array's reduce function in Swift?

有没有一种方法可以在 for 循环中但在数组的 reduce() 函数中执行类似于 break 的操作?

例如考虑我有一个数组:

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) { [=13=] ||  }

然而,对于示例中给出的数组,for 循环体将仅执行 3 次,而 reduce() 函数闭包将被触发完整 7 次。

有没有办法让 reduce() 在第 3 次迭代中也能退出(就像在 for 循环中一样)?

[更新]

我把问题简单化了。原来的问题更像这样:

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) {
    [=14=] || .isWholeMultiplesOf(2)
}

...即我有一个对象数组,我想知道是否至少有一个对象具有某种评估方法 true.

正如其他人所建议的,您可以使用 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 的较新版本在相关收集协议上公开这些函数而不是全局函数。

var flags = [false, false, true, false, false, true, false]
flags.contains(where: { [=12=] == true })
flags.contains(true) // if checking for a specific element
let index = flags.firstIndex(where: ${ [=12=] == true }) // --> 2

它在 Swift 标准库中不可用,但您可以制作它。在 my blog post 中,我描述了我提出的解决方案。在你的情况下,它在呼叫方看起来像这样:

flags.reduce(false, { [=10=] || }, until: { [=10=] })

您可以在 that Playground

中尝试一下

解决“原始问题”的现代方法是

[3, 5, 6, 7, 2, 3, 8].contains {
  [=10=].isMultiple(of: 2)
}

迭代闭包没有break,就像函数主体中不允许break一样。要模仿它,你需要抛出一个错误。

for number in numbers {
  guard !number.isMultiple(of: 2) else {
    break
  }

  print(number)
}
try? numbers.forEach {
  guard ![=12=].isMultiple(of: 2) else {
    struct Error: Swift.Error { }
    throw Error()
  }

  print([=12=])
}