将 Swift 序列转换为相邻对 [英] Transform a Swift sequence in to adjacent pairs

查看:27
本文介绍了将 Swift 序列转换为相邻对的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于我在 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.这将使它可用于任何序列,并与诸如 mapreducefilter 等方法兼容.

如何创建这样的 Sequence?以及如何编写以这种方式转换任何Sequence的方法,以便尽可能灵活地使用它?

解决方案

如果我们定义了一个扩展,我们可以使用 zip()dropFirst()Collection 类型上:

扩展集合{函数对()->AnySequence<(元素,元素)>{返回 AnySequence(zip(self, self.dropFirst()))}}

示例:

让数组 = [1, 2, 3, 4]对于数组中的 p.pairs() {打印(页)}

输出:

<前>(1, 2)(2, 3)(3, 4)

更多示例:

print(Array("abc".pairs()))//[("a", "b"), ("b", "c")]打印([1, 2, 3, 4, 5].pairs().map(+))//[3, 5, 7, 9]打印([3, 1, 4, 1, 5, 9, 2].pairs().filter(<))//[(1, 4), (1, 5), (5, 9)]

<小时>

(不像我在这个答案的第一个版本中写的......)这个当应用于 Sequence 时,方法是不安全的,因为它是不能保证一个序列可以被多次遍历无损.

这里是一个自定义迭代器类型的直接实现也适用于序列:

struct PairSequence: IteratorProtocol, Sequence {var it: S.Iterator最后一个变量:S.Element?初始化(序列:S){it = seq.makeIterator()last = it.next()}变异 func next() ->(S.Element,S.Element)?{守卫 let a = last, let b = it.next() else { return nil }最后= b返回 (a, b)}}扩展序列{函数对()->PairSequence<自身>{返回 PairSequence(seq: self)}}

示例:

print(Array([1, 2, 3, 4].pairs().pairs()))//[((1, 2), (2, 3)), ((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)].

Here are some more examples of how pairs() should behave:

  • 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.

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.

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?

解决方案

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()))
    }
}

Example:

let array = [1, 2, 3, 4]
for p in array.pairs() {
    print(p)
}

Output:

(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)]


(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)
    }
}

Example:

print(Array([1, 2, 3, 4].pairs().pairs()))
// [((1, 2), (2, 3)), ((2, 3), (3, 4))]

这篇关于将 Swift 序列转换为相邻对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆