这是另一种可能的“功能性”方法。作为一个工具,我们需要一个方法
根据谓词“截断”序列。以下用途
来自https://github.com/oisdk/SwiftSequence/blob/master/SwiftSequence/TakeDrop.swift的想法。
首先为生成器类型定义takeWhile:
extension GeneratorType {
/// Returns a new generator whose `next()` function returns the elements
/// from the given generator as long they satisfy the predicate,
/// and then returns `nil`.
func takeWhile(predicate : (Element) -> Bool) -> AnyGenerator<Element> {
var gen = self
return anyGenerator( { gen.next().flatMap( { predicate($0) ? $0 : nil }) })
}
}
现在将方法“提升”为序列类型:
extension SequenceType {
/// Returns a new sequence with all initial elements from the given sequence
/// satisfying the predicate.
func takeWhile(predicate : (Generator.Element) -> Bool) -> AnySequence<Generator.Element> {
return AnySequence( { self.generate().takeWhile(predicate) })
}
}
这个可以很通用,这里是一个简单的例子:
for i in [1, 4, 2, 5, 3].takeWhile( {$0 < 5} ) {
print(i)
}
// Output: 1 4 2
“通用前缀”函数现在可以定义为
extension String {
func commonPrefixWith(other: String) -> String {
return String(zip(self.characters, other.characters).takeWhile({$0 == $1}).map({ $1 }))
}
}
例子:
let firstString = "abc1xy"
let secondString = "abc2x"
let common = firstString.commonPrefixWith(secondString)
print(common) // abc
解释:
zip(self.characters, other.characters) 枚举两个字符序列
并行创建一个(惰性求值的)pairs序列:
("a", "a"), ("b", "b"), ("c", "c"), ("1", "2"), ("x", "x")
.takeWhile({$0 == $1}) 将此序列限制为
两个字符串中的相同字符:
("a", "a"), ("b", "b"), ("c", "c")
.map({ $1 }) 将每个元组映射到第二个元素,返回数组
[ "a", "b", "c"]
最后,String(...) 将字符组合成一个字符串。
从 Swift 4 开始, 序列有一个 prefix(while:) 方法,采用
布尔谓词,可以在这里使用而不是定义一个
自定义takeWhile方法:
extension String {
func commonPrefix(with other: String) -> String {
return String(zip(self, other).prefix(while: { $0.0 == $0.1 }).map { $0.0 })
}
}
字符串也(再次)是其字符的集合。
(从 17.05.2017 开始使用 Swift 4.0 快照进行测试。)