转置列表列表

问题描述 投票:0回答:14

假设我有

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 list transpose
14个回答
555
投票

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

说明:

我们需要知道两件事才能了解正在发生的事情:

  1. zip的签名: zip(*iterables)
     这意味着
    zip
    需要任意数量的参数,每个参数都必须是可迭代的。例如。 
    zip([1, 2], [3, 4], [5, 6])
  2. 解压缩的参数列表:给定参数序列args
    f(*args)
    将调用
    f
    ,使得
    args
    中的每个元素都是
    f
    的单独位置参数。
    如果嵌套列表的元素数量不相同(同质),
  3. 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])
。剩下的只是确保结果是列表列表而不是元组列表。


112
投票
相当于耶拿的解决方案:

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

85
投票
一种方法是使用

NumPy transpose。对于列表,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]]
    

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

28
投票
方法 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()

 变成

Python 2 中的默认填充值为

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第二个替代方案适用于不规则的二维列表,这与他的第一个代码使用numpy来转置和传递不规则的列表不同。但 None 必须是填充值。 (不,传递给内部map()的None不是填充值。这意味着没有函数来处理每一列。这些列只是传递给外部map(),后者将它们从元组转换为列表。)

在 Python 3 中的某个地方,

map()

不再忍受所有这些滥用:第一个参数不能为 None,并且不规则的迭代器只是被截断为最短。其他方法仍然有效,因为这只适用于内部 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 中,参差不齐的行不会变成参差不齐的列,它们只是被截断了。嘘嘘进步。


9
投票
三个选项可供选择:

1.带邮政编码的地图

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

2.列表理解

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

3. For 循环追加

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]
    

2
投票
import numpy as np r = list(map(list, np.transpose(l)))
    

1
投票
也许不是最优雅的解决方案,但这是一个使用嵌套 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
    

1
投票

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
投票
matrix = [[1,2,3], [1,2,3], [1,2,3], [1,2,3], [1,2,3], [1,2,3], [1,2,3]] rows = len(matrix) cols = len(matrix[0]) transposed = [] while len(transposed) < cols: transposed.append([]) while len(transposed[-1]) < rows: transposed[-1].append(0) for i in range(rows): for j in range(cols): transposed[j][i] = matrix[i][j] for i in transposed: print(i)
    

1
投票
方阵的另一种方式。没有 numpy,也没有 itertools,使用(有效的)就地元素交换。

def transpose(m): for i in range(1, len(m)): for j in range(i): m[i][j], m[j][i] = m[j][i], m[i][j]
    

1
投票
只是为了好玩:如果你想把它们全部变成字典。

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

-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
    
© www.soinside.com 2019 - 2024. All rights reserved.