将Swift序列转换为相邻对 [英] Transform a Swift sequence in to adjacent pairs
问题描述
鉴于我在Swift中有一个数组,例如[1,2,3,4]
,方法pairs()
会将其转换为元组数组:[(1,2), (2,3), (3,4)]
.
Given I've got an array in Swift such as [1,2,3,4]
, a method pairs()
will transform it in to the array of tuples: [(1,2), (2,3), (3,4)]
.
以下是pairs()
行为方式的更多示例:
Here are some more examples of how pairs()
should behave:
-
pairs([])
应该返回[]
,因为它没有成对. -
pairs([1])
也应返回[]
,因为它没有对. -
pairs([1,2])
应该是[(1,2)]
.它只有一对.
pairs([])
should return[]
as it has no pairs.pairs([1])
should also return[]
, as it has no pairs.pairs([1,2])
should be[(1,2)]
. It has just one pair.
我可以为Array
编写代码来执行此操作,但是我想提供pairs()
作为Sequence
上的扩展,以便它返回其中的Sequence
对.这将使其可以在任何序列上使用,并与map
,reduce
,filter
等方法兼容.
I can write code to do this for Array
, but I'd like to have pairs()
available as an extension on Sequence
, so that it returns a Sequence
of the pairs. This would make it useable on any sequence, and compatible with methods such as map
, reduce
, filter
, etc.
如何创建这样的Sequence
?以及如何编写以这种方式转换任何Sequence
的方法,以便可以尽可能灵活地使用它?
How do I go about creating a Sequence
like this? And how do I write the method to transform any Sequence
in this way so that it can be used as flexibly as possible?
推荐答案
如果定义扩展名,则可以使用zip()
和dropFirst()
在Collection
类型上:
We can use zip()
and dropFirst()
if we define an extension
on the Collection
type:
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)
更多示例:
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)]
(与我在此答案的第一版中写的不同...)
应用于Sequence
时,此方法并不安全,因为它是
不保证序列可以多次遍历
非破坏性地
(Unlike I wrote in the first version of this answer ...) this
approach is not safe when applied to a Sequence
, because it is
not guaranteed that a sequence can be traversed multiple times
non-destructively.
这是具有自定义迭代器类型的直接实现 也可以在序列上使用:
Here is a direct implementation with a custom iterator type which works on sequences as well:
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序列转换为相邻对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!