如何在Python中反转一个二维列表

11

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

   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]

2
这被称为“转置”,而不是“反转”。 反转列表只意味着将其颠倒,而不是将其旋转90度。 - abarnert
3个回答

15

以下是关于 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]]

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

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

但是如果有超过两行呢? - Aswin Murugesh
@AswinMurugesh 它适用于任意数量的行:zip([1,2,3],[4,5,6],[7,8,9]) 返回 [(1, 4, 7), (2, 5, 8), (3, 6, 9)]。 - aga
如果所有东西都存储在变量中,我能用这个方法吗?例如,如果我有一个名为results的二维列表,并且我不确定它有多大,我该如何将其传递给zip函数? - DannyD
@RDoolabh 我已经更新了我的答案,包含你所需要的信息。 - aga
正确的英文术语是Unpacking Argument Lists。(文档小心地避免给实际的_operator_命名,总是使用“*运算符”,我认为部分原因是每个人都称其为“splat”运算符,没有人想将其奉为经典,并且部分原因是为了避免解释在不同上下文中*是不同的运算符——虽然它实际上并不是,但在你准备解释dunder方法之前,这是一个难点。) - abarnert

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将会是results中的每个元素,也就是说它将会是[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,否则你会得到一个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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接