假设我在 Swift 中有一个数组,例如 [1,2,3,4]
,pairs()
方法会将其转换为数组元组数:[(1,2), (2,3), (3,4)]
。
以下是 pairs()
应如何表现的更多示例:
pairs([])
应返回[]
,因为它没有对。pairs([1])
还应该返回[]
,因为它没有对。pairs([1,2])
应为[(1,2)]
。它只有一对。
我可以编写代码来为Array
执行此操作,但我希望将pairs()
用作Sequence
的扩展,以便它返回该对的Sequence
。这将使其可用于任何序列,并与 map
、reduce
、filter
等方法兼容。
如何创建这样的序列
?我该如何编写方法来以这种方式转换任何Sequence
,以便它可以尽可能灵活地使用?
最佳答案
如果我们定义扩展,我们可以使用 zip()
和 dropFirst()
在 Collection
类型上:
extension Collection {
func pairs() -> AnySequence<(Element, Element)> {
return AnySequence(zip(self, self.dropFirst()))
}
}
示例:
let array = [1, 2, 3, 4]
for p in array.pairs() {
print(p)
}
输出:
(1, 2) (2, 3) (3, 4)
More examples:
print(Array("abc".pairs()))
// [("a", "b"), ("b", "c")]
print([1, 2, 3, 4, 5].pairs().map(+))
// [3, 5, 7, 9]
print([3, 1, 4, 1, 5, 9, 2].pairs().filter(<))
// [(1, 4), (1, 5), (5, 9)]
<小时/>
(与我在这个答案的第一个版本中写的不同......)
应用于序列
时,该方法并不安全,因为它是
不保证一个序列可以被遍历多次
非破坏性。
这是使用自定义迭代器类型的直接实现 它也适用于序列:
struct PairSequence<S: Sequence>: IteratorProtocol, Sequence {
var it: S.Iterator
var last: S.Element?
init(seq: S) {
it = seq.makeIterator()
last = it.next()
}
mutating func next() -> (S.Element, S.Element)? {
guard let a = last, let b = it.next() else { return nil }
last = b
return (a, b)
}
}
extension Sequence {
func pairs() -> PairSequence<Self> {
return PairSequence(seq: self)
}
}
示例:
print(Array([1, 2, 3, 4].pairs().pairs()))
// [((1, 2), (2, 3)), ((2, 3), (3, 4))]
关于swift - 将 Swift 序列转换为相邻对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57474431/