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

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

问题描述

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

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屋!

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