Cri*_*ian 480 python transpose list matrix
我有一个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])
Run Code Online (Sandbox Code Playgroud)
是否有内置函数可以做到这一点?
Pat*_*ick 739
zip是它自己的逆!如果您使用特殊*运算符.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
Run Code Online (Sandbox Code Playgroud)
这种方式的工作方式是zip使用参数调用:
zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
Run Code Online (Sandbox Code Playgroud)
...除了参数zip直接传递给(在转换为元组之后),所以不必担心参数的数量太大.
And*_*ius 26
你也可以这样做
result = ([ a for a,b in original ], [ b for a,b in original ])
Run Code Online (Sandbox Code Playgroud)
它应该更好地扩展.特别是如果Python不擅长扩展列表推导,除非需要.
(顺便说一句,它产生了一个2元组(对)列表,而不是像元组列表那样zip.)
如果生成器而不是实际列表都可以,那么这样做:
result = (( a for a,b in original ), ( b for a,b in original ))
Run Code Online (Sandbox Code Playgroud)
在您询问每个元素之前,生成器不会遍历列表,但另一方面,它们会保留对原始列表的引用.
小智 21
如果您的列表长度不同,则可能不希望按照Patricks的说法使用zip.这有效:
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
Run Code Online (Sandbox Code Playgroud)
但是使用不同的长度列表,zip会将每个项目截断为最短列表的长度:
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e')]
Run Code Online (Sandbox Code Playgroud)
您可以使用没有函数的map来填充空结果,而不是:
>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]
Run Code Online (Sandbox Code Playgroud)
zip()虽然略快.
was*_*ans 15
我喜欢zip(*iterable)在我的程序中使用(这是你正在寻找的代码段),如下所示:
def unzip(iterable):
return zip(*iterable)
Run Code Online (Sandbox Code Playgroud)
我发现unzip更具可读性.
Noy*_*282 12
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple([list(tup) for tup in zip(*original)])
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
Run Code Online (Sandbox Code Playgroud)
在问题中给出一个列表元组.
list1, list2 = [list(tup) for tup in zip(*original)]
Run Code Online (Sandbox Code Playgroud)
解压缩两个列表.
def transpose_finite_iterable(iterable):
return zip(*iterable) # `itertools.izip` for Python 2 users
Run Code Online (Sandbox Code Playgroud)
工作正常的有限可迭代(例如序列像list/ tuple/ str)的(可能是无限的)iterables可以像图示
| |a_00| |a_10| ... |a_n0| |
| |a_01| |a_11| ... |a_n1| |
| |... | |... | ... |... | |
| |a_0i| |a_1i| ... |a_ni| |
| |... | |... | ... |... | |
Run Code Online (Sandbox Code Playgroud)
在哪里
n in ?,a_ij对应于-th iterable 的j-th 元素i,申请后transpose_finite_iterable我们得到
| |a_00| |a_01| ... |a_0i| ... |
| |a_10| |a_11| ... |a_1i| ... |
| |... | |... | ... |... | ... |
| |a_n0| |a_n1| ... |a_ni| ... |
Run Code Online (Sandbox Code Playgroud)
这种情况的 Python 示例,其中a_ij == j,n == 2
>>> from itertools import count
>>> iterable = [count(), count()]
>>> result = transpose_finite_iterable(iterable)
>>> next(result)
(0, 0)
>>> next(result)
(1, 1)
Run Code Online (Sandbox Code Playgroud)
但是我们不能transpose_finite_iterable再次使用来返回原始结构,iterable因为result是有限迭代的无限迭代(tuple在我们的例子中是 s):
>>> transpose_finite_iterable(result)
... hangs ...
Traceback (most recent call last):
File "...", line 1, in ...
File "...", line 2, in transpose_finite_iterable
MemoryError
Run Code Online (Sandbox Code Playgroud)
那么我们该如何处理这个案子呢?
deque在我们查看了itertools.tee函数的文档之后,有一个 Python 配方,经过一些修改可以帮助我们解决这个问题。
def transpose_finite_iterables(iterable):
iterator = iter(iterable)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
Run Code Online (Sandbox Code Playgroud)
让我们检查
>>> from itertools import count
>>> iterable = [count(), count()]
>>> result = transpose_finite_iterables(transpose_finite_iterable(iterable))
>>> result
(<generator object transpose_finite_iterables.<locals>.coordinate at ...>, <generator object transpose_finite_iterables.<locals>.coordinate at ...>)
>>> next(result[0])
0
>>> next(result[0])
1
Run Code Online (Sandbox Code Playgroud)
现在我们可以定义通用函数来处理迭代的迭代,其中一些是有限的,另一个可能是无限的,使用functools.singledispatch装饰器,如
from collections import (abc,
deque)
from functools import singledispatch
@singledispatch
def transpose(object_):
"""
Transposes given object.
"""
raise TypeError('Unsupported object type: {type}.'
.format(type=type))
@transpose.register(abc.Iterable)
def transpose_finite_iterables(object_):
"""
Transposes given iterable of finite iterables.
"""
iterator = iter(object_)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
def transpose_finite_iterable(object_):
"""
Transposes given finite iterable of iterables.
"""
yield from zip(*object_)
try:
transpose.register(abc.Collection, transpose_finite_iterable)
except AttributeError:
# Python3.5-
transpose.register(abc.Mapping, transpose_finite_iterable)
transpose.register(abc.Sequence, transpose_finite_iterable)
transpose.register(abc.Set, transpose_finite_iterable)
Run Code Online (Sandbox Code Playgroud)
它可以被认为是它自己的逆(数学家称这种函数为“对合”),属于有限非空迭代的二元运算符类。
作为singledispatching 的一个好处,我们可以处理numpy像这样的数组
import numpy as np
...
transpose.register(np.ndarray, np.transpose)
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它
>>> array = np.arange(4).reshape((2,2))
>>> array
array([[0, 1],
[2, 3]])
>>> transpose(array)
array([[0, 2],
[1, 3]])
Run Code Online (Sandbox Code Playgroud)
由于transpose返回迭代器,并且如果有人想在 OP 中使用tupleof lists - 这可以使用map内置函数进行额外制作,例如
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple(map(list, transpose(original)))
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
Run Code Online (Sandbox Code Playgroud)
我已经添加推广解决方案lz包从0.5.0版本,可以像使用
>>> from lz.transposition import transpose
>>> list(map(tuple, transpose(zip(range(10), range(10, 20)))))
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)]
Run Code Online (Sandbox Code Playgroud)
没有解决方案(至少是显而易见的)来处理潜在无限迭代的潜在无限迭代,但这种情况不太常见。
| 归档时间: |
|
| 查看次数: |
148092 次 |
| 最近记录: |