转置列表的列表
- 2024-11-20 08:44:00
- admin 原创
- 7
问题描述:
假设我有
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)]
但我必须有列表作为结果的元素。
解决方案 1:
对于矩形数据
(或将每“列”限制为最短输入“行”的长度)
在 Python 3.x 中,使用:
# short circuits at shortest nested list if table is jagged:
list(map(list, zip(*l)))
在 Python 2.x 中,使用:
# short circuits at shortest nested list if table is jagged:
map(list, zip(*l))
这里有两件重要的事情需要理解:
zip的签名:
zip(*iterables)
这意味着zip
需要任意数量的参数,每个参数都必须是可迭代的。例如zip([1, 2], [3, 4], [5, 6])
。解包参数列表:给定一个参数序列
args
,f(*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])
。另请参阅:将元组扩展为参数
剩下的只是通过使用map
从每个元组创建一个列表来确保结果是列表的列表而不是元组的列表。
对于锯齿状数据
None
用输出中的值填充较短的行import itertools
(这是在标准库中),然后:
在 Python 3.x 中,使用:
list(map(list, itertools.zip_longest(*l, fillvalue=None)))
在 Python 2.x 中,使用:
list(map(list, itertools.izip_longest(*l, fillvalue=None)))
解决方案 2:
相当于 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]]
解决方案 3:
其中一种方法是使用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]]
解决方案 4:
只是为了好玩,有效的矩形并假设 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]]
解决方案 5:
方法 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]]
方法 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()
变成
itertools.izip_longest()
在 Python 2 中itertools.zip_longest()
在 Python 3 中
默认的填充值是None
。感谢@jena 的回答,其中map()
将内部元组更改为列表。这里它将迭代器转换为列表。感谢@Oregano 和@badp 的评论。
在 Python 3 中,传递结果list()
以获取与方法 2 相同的二维列表。
方法 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 —在Python 3.6 中已map()
损坏map()
>>> 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 来转置和传递不规则的列表。但是 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 中,参差不齐的行不会变成参差不齐的列,它们只是被截断了。真是进步啊。
解决方案 6:
有三个选项可供选择:
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]
解决方案 7:
import numpy as np
r = list(map(list, np.transpose(l)))
解决方案 8:
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
解决方案 9:
也许不是最优雅的解决方案,但这是一个使用嵌套 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
解决方案 10:
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)
解决方案 11:
方阵的另一种方法。没有 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]
解决方案 12:
只是为了好玩:如果你想把它们全部变成字典。
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}]
解决方案 13:
以下是转置不一定是方阵的列表列表的解决方案:
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])
解决方案 14:
#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
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件