【问题标题】:How to zip two sequences (one shifted by N elements)? [duplicate]如何压缩两个序列(一个由 N 个元素移动)? [复制]
【发布时间】:2020-06-13 08:28:43
【问题描述】:

我有两个列表AB,我想遍历元素对(A[0], B[2])(A[1], B[3]) 等。 如果没有班次,我可以使用zip(A, B) 来有效地做到这一点。

在这个例子中,移位是 2,但可能发生我需要移位 N。如何有效地做到这一点(不索引到两个列表中)?

【问题讨论】:

标签: python python-3.x iterator


【解决方案1】:

我认为一个简洁的方法是

zipped = zip(list1, list2[n:])

其中n 是一个表示偏移量的整数。

【讨论】:

  • 问题在于它似乎至少需要len(list2) - n 额外的内存才能获得几乎完整的list2 副本,不是吗?
  • 不会复制列表中的数据,但会创建一个可能需要大量内存的新 slice 对象。另一方面,切片创建速度很快。
  • @sophros,据我了解,当列表被切片时,列表元素,即 data 不会被复制。但是,会创建一个切片对象,并复制指向 data 的指针。我认为每个指针都是8b,并且对象本身有一些内存。无论如何,切片不太可能导致性能问题。另外,我不确定您提出的解决方案是否比这个较短的替代方案更有效。
【解决方案2】:

最终,我得到了以下通用函数:

def zip_shift(s1, s2, shift, placeholder):
    i1 = iter(s1)
    i2 = iter(s2)

    while shift > 0:
        yield placeholder, next(i2)  # leave only next(i2) if no placeholder pairs are needed
        shift -= 1

    yield from zip(i1, i2)  # or return zip

上述函数的工作方式类似于generator,它首先填充placeholdershift 次,而不是从第二个序列s2 中获取值。之后,它就像zip 一样工作。 yield fromrelatively new construct(从 Python 3.3 开始)。上面有subtle differences between yield from and return但是这种情况可以忽略。

当然,如果shift 的值几乎为 1(带有占位符的对除外),也可以通过以下方式实现:

zip(s1, next(s2))

zip 一样,序列不必具有相同的长度。只要较短的序列没有用完,生成器就会工作。

【讨论】:

    猜你喜欢
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 2016-07-22
    相关资源
    最近更新 更多