如果这是一次性问题,那么任何小的 for 循环都可以,但探索通用解决方案是一个有趣的问题。首先,我假设您的意思是每个元素都必须比前一个大一个,而不仅仅是按顺序。
让我们构建一个通用的方法来回答“这个集合中的所有元素对都遵守一些规则”。首先,如果能有一种通用的方式来表达“做所有事情?”,那就太好了。
extension Sequence {
func all(pass predicate: (Element) -> Bool) -> Bool {
// If nothing is false, everything is true
return !self.contains(where: { !predicate($0) })
}
}
这会返回一个序列的所有元素是否都遵守某个规则。
现在我们可以问一个问题:集合的所有成对元素是否都遵守某些规则:
extension Collection {
func passesForConsecutiveValues(_ predicate:(Element, Element) -> Bool) -> Bool {
return zip(self, dropFirst()).all(pass: predicate)
}
}
zip(x, x.dropFirst() 只是创建“成对元素”,然后我们问“它们都满足我们的规则吗?”例如:
// Are all elements one more than their predecessor?
[1,2,4,5].passesForConsecutiveValues { $1 == $0 + 1 } // true
现在您可能已经注意到我在中间从 Sequence 切换到 Collection。为什么?因为zip(x, x.dropFirst()) 没有在任意序列上定义。您可能只被允许对一个序列进行一次迭代。不幸的是,没有办法知道;它在文档中被认为是“关于序列的特殊知识”。呜呜。我想念 Scala 的 TraversableOnce vs. Sequence,它将需求转移到类型中。
也就是说,我们绝对可以为 Sequence 构建这个。我们只需要为zip(x, x.dropFirst()) 构建一个替代品。我们称它为pairwise,它会返回一个迭代器:
extension Sequence {
func pairwise() -> AnyIterator<(Element, Element)> {
var it = makeIterator()
guard var last_value = it.next() else { return AnyIterator{ return nil } }
return AnyIterator {
guard let value = it.next() else { return nil }
defer { last_value = value }
return (last_value, value)
}
}
}
这样,我们可以在 Sequence 上构建它:
extension Sequence {
func passesForConsecutiveValues(_ predicate:(Element, Element) -> Bool) -> Bool {
return pairwise().all(pass: predicate)
}
}