转置/解压函数(zip的反函数)是什么?

605

我有一个由2个元素的元组列表,我想将它们转换成2个列表,其中第一个列表包含每个元组中的第一个元素,第二个列表包含第二个元素。

例如:

original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
# and I want to become...
result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])

有没有内置函数可以做到这一点?


8
下面有很棒的答案,但也请看一下numpy的转置功能 - opyate
5
请参考这个很好的答案,使用生成器而不是列表来执行相同的操作:如何使用生成器解压缩迭代器 - YvesgereY
为什么zip被称为转置? - Charlie Parker
1
@CharlieParker,因为它类似于数学中的矩阵转置。如果最初每个嵌套序列中的数据被视为矩阵的“行”,那么其值将最终出现在由输出表示的相应矩阵的“列”中。 - Karl Knechtel
1
不是真正的反转,但在某些情况下,d=dict(original) 后跟 d.keys()d.values() 可能很方便。 - djvg
14个回答

1

由于它返回元组(并且可能使用大量内存),对我来说,zip(*zipped) 技巧似乎更聪明而不是有用。

这里有一个函数,实际上会给你 zip 的反转。

def unzip(zipped):
    """Inverse of built-in zip function.
    Args:
        zipped: a list of tuples

    Returns:
        a tuple of lists

    Example:
        a = [1, 2, 3]
        b = [4, 5, 6]
        zipped = list(zip(a, b))

        assert zipped == [(1, 4), (2, 5), (3, 6)]

        unzipped = unzip(zipped)

        assert unzipped == ([1, 2, 3], [4, 5, 6])

    """

    unzipped = ()
    if len(zipped) == 0:
        return unzipped

    dim = len(zipped[0])

    for i in range(dim):
        unzipped = unzipped + ([tup[i] for tup in zipped], )

    return unzipped

不断重新创建元组对我来说似乎并不高效,但是您可以使用双端队列扩展此方法,它可以预分配内存。 - Charlie Clark

1
虽然zip(*seq)非常有用,但对于非常长的序列可能不太适用,因为它会创建一个要传递的值元组。例如,我一直在使用一个包含超过一百万个条目的坐标系统,并发现直接创建序列要快得多。
通用方法可能是这样的:
from collections import deque
seq = ((a1, b1, …), (a2, b2, …), …)
width = len(seq[0])
output = [deque(len(seq))] * width # preallocate memory
for element in seq:
    for s, item in zip(output, element):
        s.append(item)

但是,根据您想要对结果进行的操作,集合的选择可能会有很大的差异。在我的实际使用情况中,使用集合而不是内部循环,明显比其他方法更快。

另外,正如其他人所指出的那样,如果您正在处理数据集,可能更好地使用Numpy或Pandas集合。


0
只是简单概括一下:
# data
a = ('a', 'b', 'c', 'd')
b = (1, 2, 3, 4)

# forward
zipped = zip(a, b)  # [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

# reverse
a_, b_ = zip(*zipped)

# verify
assert a == a_
assert b == b_

-1
这是一个简单的一行代码,可以生成所需的输出:
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
list(zip(*original))
# [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接