我们来看一个例子:
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
我正在寻找的结果是:
r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
而不是
r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
Python 3:
# short circuits at shortest nested list if table is jagged:
list(map(list, zip(*l)))
# discards no data if jagged and fills short nested lists with None
list(map(list, itertools.zip_longest(*l, fillvalue=None)))
Python 2:
map(list, zip(*l))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
解释:
为了理解发生了什么,我们需要知道两件事情:
zip(*iterables)
这意味着zip
期望任意数量的参数,每个参数都必须是可迭代的。 例如:zip([1, 2], [3, 4], [5, 6])
。args
组成的序列,f(*args)
将调用f
,以便f
中的每个元素都是args
中的一个单独的位置参数。itertools.zip_longest
不会丢弃任何数据,即使嵌套列表的元素数量不同(非同构),而是填充较短的嵌套列表,然后将它们进行压缩。回到问题中的输入l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
,zip(*l)
等同于zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
。其余的只是确保结果是一个列表的列表而不是一个元组的列表。
类似于Jena的解决方案:
>>> l=[[1,2,3],[4,5,6],[7,8,9]]
>>> [list(i) for i in zip(*l)]
... [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map()
更受欢迎,因此这种解决方案是最符合Python精神的。 - perror使用NumPy转置是一种方法。对于一个列表 a:
>>> import numpy as np
>>> np.array(l).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
或者另一个没有 zip 的版本(Python < 3):
>>> map(list, map(None, *l))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
或者对于Python版本>=3:
>>> list(map(lambda *x: list(x), *l))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
map(lambda *a: list(a), *l)
- Lee Dmap(None, ...)
在 Py3 中似乎无法正常工作。生成器被创建,但 next()
立即引发错误:TypeError: 'NoneType' object is not callable
。 - Mad Physicist仅供娱乐,假定m[0]存在的有效矩形。
>>> m = [[1,2,3],[4,5,6],[7,8,9]]
>>> [[row[i] for row in m] for i in range(len(m[0]))]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[[j[i] for j in l] for i in range(len(l[0]))]
。当然,你必须确保列表 l
不为空。 - Lee DNaN
填充,如果需要维护低级数据结构。如果badp示例中缩短的行在中间而不是末尾,则必须使用NaN
来维护序列数据结构,但如果将其转换为允许稀疏性的内容(如dict
的dict
或scipy.sparse
矩阵),则不需要这样做。 - hobs方法1和方法2适用于Python 2或3,并且适用于不规则的矩形二维列表。这意味着内部列表不需要彼此具有相同的长度(不规则),也不需要与外部列表具有相同的长度(矩形)。其他方法,嗯,比较复杂。
import itertools
import six
list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]
map()
,zip_longest()
>>> list(map(list, six.moves.zip_longest(*list_list, fillvalue='-')))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]
six.moves.zip_longest()
成为:
itertools.izip_longest()
在Python 2中itertools.zip_longest()
在Python 3中默认的填充值是None
。感谢@jena的答案,其中map()
将内部元组更改为列表。这里它将迭代器转换为列表。感谢@Oregano和@badp的评论。
在Python 3中,将结果传递给list()
以获得与方法2相同的二维列表。
zip_longest()
>>> [list(row) for row in six.moves.zip_longest(*list_list, fillvalue='-')]
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]
map()
的map()
— 在Python 3.6中失效>>> map(list, map(None, *list_list))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]]
这个非常紧凑的@SiggyF的第二个选择适用于不整齐的二维列表,与他的第一个代码不同,后者使用numpy进行转置和通过不整齐的列表。但None必须是填充值。(不,传递给内部map()的None不是填充值。它意味着没有函数来处理每一列。这些列只是通过外部map()传递,将它们从元组转换为列表。)
在Python 3的某个地方,map()
已经停止容忍所有这些滥用:第一个参数不能是None,不整齐的迭代器只会被截断到最短。其他方法仍然有效,因为这仅适用于内部map()。
map()
of map()
重访>>> list(map(list, map(lambda *args: args, *list_list)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]] // Python 2.7
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]] // 3.6+
哎呀,在Python 3中,那些参差不齐的行并没有变成参差不齐的列,它们只是被截断了。进步真可怜。
solution1 = map(list, zip(*l))
solution2 = [list(i) for i in zip(*l)]
solution3 = []
for i in zip(*l):
solution3.append((list(i)))
print(*solution1)
print(*solution2)
print(*solution3)
# [1, 4, 7], [2, 5, 8], [3, 6, 9]
import numpy as np
r = list(map(list, np.transpose(l)))
np.transpose(l).tolist()
。 - jareddef transpose(lst):
newlist = []
i = 0
while i < len(lst):
j = 0
colvec = []
while j < len(lst):
colvec.append(lst[j][i])
j = j + 1
newlist.append(colvec)
i = i + 1
return newlist
只是为了好玩:如果你想把它们全部变成字典。
In [1]: l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
...: fruits = ["Apple", "Pear", "Peach",]
...: [dict(zip(fruits, j)) for j in [list(i) for i in zip(*l)]]
Out[1]:
[{'Apple': 1, 'Pear': 4, 'Peach': 7},
{'Apple': 2, 'Pear': 5, 'Peach': 8},
{'Apple': 3, 'Pear': 6, 'Peach': 9}]
more_itertools.unzip()
很容易阅读,而且它也可以与生成器一起使用。
import more_itertools
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r)) # a list of lists
或者等价地
import more_itertools
l = more_itertools.chunked(range(1,10), 3)
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r)) # a list of lists
l
不是长度相等的(例如,某些行比其他行短),zip
函数将 不会 进行补偿,而是从输出中裁剪掉相应的行。因此,l=[[1,2],[3,4],[5]]
会给出[[1,3,5]]
的结果。 - badpitertools
模块中的zip_longest()
函数可以处理长度不同的列表。请参阅文档。 - Oreganolist(zip(*l))
也能正常工作。 - Stefanozip(*l)
也有效),但你得到的是一个元组列表,而不是一个列表列表。当然,list(list(it))
始终等同于list(it)
。 - Alex Shpilkin