转置列表的列表

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)] 但我必须有列表作为结果的元素...

问题描述:

假设我有

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

这里有两件重要的事情需要理解:

  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])。另请参阅:将元组扩展为参数

剩下的只是通过使用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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用