转置列表清单


241

让我们来:

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)]

非常感激

Answers:


336

怎么样

map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

对于python 3.x,用户可以使用

list(map(list, zip(*l)))

说明:

我们需要了解两件事以了解正在发生的事情:

  1. zip的签名:zip(*iterables)这意味着zip需要任意数量的参数,每个参数必须是可迭代的。例如zip([1, 2], [3, 4], [5, 6])
  2. 未打包的参数列表:给定一个参数序列argsf(*args)将调用f使得每个元素args是一个单独的位置参数f

回到问题的输入l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]zip(*l)将等效于zip([1, 2, 3], [4, 5, 6], [7, 8, 9])。剩下的只是确保结果是列表列表而不是元组列表。


67
请注意:如果l大小不均(例如,某些行比其他行短),zip不会对其进行补偿,而是从输出中切掉行。所以l=[[1,2],[3,4],[5]]给你[[1,3,5]]
badp 2013年

29
itertools功能zip_longest()适用于不均匀列表。参见DOCS
牛至

13
一个答案的解释会很好:)
鲍里斯·库尔津

7
我认为甚至list(zip(*l))可以在Python 3中正常
Stefano

3
@Stefano它可以工作(就像zip(*l)Python 2一样),但是您得到一个元组列表,而不是列表列表。当然,list(list(it))总是和相同list(it)
Alex Shpilkin

62

一种方法是使用NumPy转置。有关列表,请:

>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

或另一个没有拉链的人:

>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

8
爱你的第二个-我没想到map可以做到。不过,这是一个不需要2个电话的细微改进:map(lambda *a: list(a), *l)
Lee D

7
因为它可以处理不均匀的列表,所以这不是一个更好的答案吗?
2014年

15
map(None, ...)似乎不适用于Py3。生成器已创建,但next()立即引发错误:TypeError: 'NoneType' object is not callable
疯狂物理学家,2013年

57

等效于耶拿的解决方案:

>>> 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]]

12
由于现在首选列表理解map(),因此该解决方案是Python精神中最丰富的解决方案...
perror

26

只是为了好玩,有效的矩形并假设存在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]]

这就是我一直在寻找的东西,我无法理解。
@jena

3
是的,花了一些时间才能做到这一点。好的,很多尝试。
matchew 2011年

9
仍然不太正确-仅在尺寸为正方形时才起作用!应该是:[[j[i] for j in l] for i in range(len(l[0]))]。当然,您必须确保列表l不为空。
李D

@LeeD在耶拿的例子中仍然对我不起作用l = [[1,2],[3,4],[5]]
滚刀2013年

3
@hobs那是badp的例子,回应耶拿。但是,我不确定这对我是否有意义。IMO,换位表示一个矩形矩阵-当表示为列表列表时,这意味着所有内部列表的长度必须相同。您希望本示例的“换位”结果是什么?
Lee D

22

方法1和2在Python 2或3中工作,并且在粗糙的矩形 2D列表中工作。这意味着内部列表的长度不必彼此相同(参差不齐),也可以不必与外部列表的长度相同(矩形)。其他方法,很复杂。

设置

import itertools
import six

list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]

方法1 — 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() 变成

默认填充值为None。感谢@jena的answer,其中map()将内部元组更改为列表。在这里它将迭代器变成列表。感谢@Oregano和@badp的评论

在Python 3中,将结果传递通过list()以获得与方法2相同的2D列表。


方法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, '-']]

@ inspectorG4dget替代


方法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,适用于参差不齐的 2D列表,与他的第一个使用numpy进行转置并通过参差不齐的列表的代码不同。但是,没有一个必须是填充值。(不,传递给内部map()的None不是填充值。这意味着没有处理每一列的功能。这些列只是传递给外部map(),后者将它们从元组转换为列表。

在Python 3中的某个地方,map()不再忍受所有这种滥用:第一个参数不能为None,并且衣衫it的迭代器只会被截短到最短。其他方法仍然有效,因为这仅适用于内部map()。


方法4 - map()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中,行行变得不成为行列,它们只是被截断了。嘘声进步。


7

三个选项可供选择:

1.使用Zip映射

solution1 = map(list, zip(*l))

2.列表理解

solution2 = [list(i) for i in zip(*l)]

3.对于循环追加

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]

0

也许不是最优雅的解决方案,但这是使用嵌套while循环的解决方案:

def 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


0

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

-1

这是转置不一定为正方形的列表列表的解决方案:

maxCol = len(l[0])
for row in l:
    rowLength = len(row)
    if rowLength > maxCol:
        maxCol = rowLength
lTrans = []
for colIndex in range(maxCol):
    lTrans.append([])
    for row in l:
        if colIndex < len(row):
            lTrans[colIndex].append(row[colIndex])

-2
    #Import functions from library
    from numpy import size, array
    #Transpose a 2D list
    def transpose_list_2d(list_in_mat):
        list_out_mat = []
        array_in_mat = array(list_in_mat)
        array_out_mat = array_in_mat.T
        nb_lines = size(array_out_mat, 0)
        for i_line_out in range(0, nb_lines):
            array_out_line = array_out_mat[i_line_out]
            list_out_line = list(array_out_line)
            list_out_mat.append(list_out_line)
        return list_out_mat
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.