【问题标题】:How to I invert a 2d list in python [duplicate]如何在python中反转二维列表[重复]
【发布时间】:2013-12-15 06:12:36
【问题描述】:

我有一个这样的二维列表:

   1   2   3

   4   5   6

我想做这个:

   1   4

   2   5

   3   6

我尝试执行 for 循环并切换每个值,但我不断收到索引越界错误。这是我所拥有的:

for i in results:
    for j in range(numCenturies):
        rotated[i][j] = results [j][i]

【问题讨论】:

  • 这称为“转置”,而不是“倒置”。倒置列表只是意味着将其倒置,而不是将其旋转 90 度。

标签: python list transpose


【解决方案1】:

来自zip函数的python文档:

此函数返回一个元组列表,其中第 i 个元组包含来自每个参数序列或可迭代对象的第 i 个元素。返回的列表在长度上被截断为最短参数序列的长度。当有多个长度相同的参数时,zip() 类似于 map(),初始参数为 None。使用单个序列参数,它返回一个 1 元组列表。没有参数,它返回一个空列表。

例子:

zip([1, 2, 3], [4, 5, 6]) # returns [(1, 4), (2, 5), (3, 6)]

如果您需要结果是列表列表,而不是元组列表,您可以使用列表推导:

[list(x) for x  in zip([1, 2, 3], [4, 5, 6], [7, 8, 9])] # returns [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

如果您的所有变量都存储在一个 2d 列表中,并且您希望将其传递给 zip 函数,您可以使用以下方法(我将其称为 星号表示法,因为我可以'不记得正确的英文术语):

results = [[1, 2, 3], [4, 5, 6]]
zip(*results) # returns [(1, 4), (2, 5), (3, 6)]

【讨论】:

  • 但是如果多于两行呢?
  • @AswinMurugesh 它适用于提供的任意数量的行: zip([1,2,3],[4,5,6],[7,8,9]) 返回 [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
  • 如果所有内容都存储在变量中,我可以使用它吗?例如,如果我有一个名为 results 的二维列表,但我不确定它有多大,如何将它传递给 zip 函数?
  • @RDolabh 我已经用您正在寻找的信息更新了我的答案。
  • 正确的英文术语是Unpacking Argument Lists。 (文档小心地避免给实际的 operator 起名字,总是使用“* operator”,我相信部分原因是每个人都称它为“splat”运算符,没有人愿意奉承在文档中,部分原因是为了避免解释 * 在不同的上下文中是如何成为不同的运算符的——实际上不是,但在你准备好解释难以解释的 dunder 方法之前。)跨度>
【解决方案2】:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html

>>> from numpy import transpose
>>> transpose([[1,2,3],[4,5,6]])
array([[1, 4],
       [2, 5],
       [3, 6]])

【讨论】:

    【解决方案3】:

    zip 是这样做的正确方法,如 aga 所示。

    但如果您想知道为什么您的原始代码不起作用:

    for i in results:
        for j in range(numCenturies):
            rotated[i][j] = results [j][i]
    

    这里有两个明显的问题,而且可能还有另外两个问题。 (由于您没有向我们展示足够多的代码或数据来确定,我不能保证这两个可能。)

    大概results 看起来像这样:

    results = [[1, 2, 3], [4, 5, 6]]
    

    当您使用for i in results 时,这意味着i 将是结果中的每个元素——也就是说,它将是[1, 2, 3],然后是[4, 5, 6]。您不能将列表用作列表的索引,因此可以保证为您提供TypeError: list indices must be integers, not list。

    要解决此问题,您需要:

    for i in range(len(results)):
    

    ……或……

    for i, row in enumerate(results):
    

    接下来,results[j][i] 肯定会提升IndexError: list index out of range,因为i 是每个行 编号,但您正试图将其用作列数字。如果您要遍历 results 的行和列,您需要这样:

    rotated[j][i] = results[i][j]
    

    接下来,除非您用 3 个列表预先填充 rotated,每个列表都预先填充 2 个某种对象,否则您将获得一个 IndexError: list assignment index out of range。

    要解决此问题,您需要预先填写 rotated,如下所示:

    rotated = [[None for j in range(2)] for i in range(3)]
    

    ……或……

    rotated = [[None, None], [None, None], [None, None]]
    

    最后,我打赌numCenturies 是3,在这种情况下,一旦j 达到2,你就会得到另一个IndexError: list index out of range。这里最简单的做法是只使用行的长度;这样一来,就不会出现一个错误的错误。

    把它们放在一起:

    rotated = [[None for j in range(2)] for i in range(3)]
    for i, row in enumerate(results):
        for j, value in enumerate(row):
            rotated[j][i] = value
    

    但总的来说,Python 为您提供了比预先创建数组和遍历索引来填充值更简单的方法。你可以使用append——或者,更好的是,列表理解。或者,更好的是,找到一种更高级别的方式来编写您的使用,例如对zip 的一次调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-09
      • 2017-12-06
      • 2013-05-09
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      • 2022-07-06
      • 2016-07-14
      相关资源
      最近更新 更多