旋转图像列表理解

时间:2017-11-01 08:14:50

标签: python matrix in-place

在解决矩阵旋转问题时,我遇到了一个解决方案。问题要求将矩阵旋转90度。

def rotateImage(a):
    rows = len(a)
    cols = len(a[0])
    a=a[::-1]
    return [[m[i] for m in  a] for i in range(cols)]

有人可以帮助我将这个列表理解分解为常规for循环并理解程序的流程

2 个答案:

答案 0 :(得分:1)

你有一个嵌套列表理解,一个外部列表理解为每次迭代创建一个新列表。

您可以通过从左到右阅读forif组件作为嵌套块来解构任何列表理解。第一个for之前的 Everything 是生成列表元素的表达式。

所以基本结构是:

[<expression> for <targets> in <iterable> <optionally more if and for>]

总是可以转换为常规循环:

_result = []
for <targets> in <iterable>:
    <optionally more if and for blocks, add a new level each time>
        _result.append(<expression>)

我在_result中添加了作为生成列表的显式名称;请注意,每次迭代都会附加<expression>的结果。

您的示例分解为两个列表推导。外循环是这样的:

[[m[i] for m in  a] for i in range(cols)]
# \              /      |     \       /
#   <expression>    <targets>  <iterable>

所以[m[i] for m in a]就是这里的表达!把它写出来就成了:

_result_outer = []
for i in range(cols):
    _result_outer.append([m[i] for m in  a])

内部列表理解很简单:

_result_inner = []
for m in a:
    _result_inner.append(m[i])

如果你将这两者放在一起,你会得到:

_result_outer = []
for i in range(cols):
    _result_inner = []
    for m in a:
        _result_inner.append(m[i])
    _result_outer.append(_result_inner)

现在,您可以看到每次在内部循环中使用外部循环中的i目标。因为i遍历列数,但m是一行,所以首先会生成一个列表,其中包含第一列,第二列,第三列,第三列等所有值。

列表理解之前的行颠倒行:

a = a[::-1]

这将占用所有行,从最后一行到第一行(向后退步,步长为-1)。这使得列表推导以相反的顺序循环遍历行。

代码可以清理和改进一点。例如,rows变量从不使用,我们可以使用reversed() function以相反的顺序循环遍历列表而不创建副本:

def rotateImage(a):
    cols = len(a[0])
    return [[m[i] for m in reversed(a)] for i in range(cols)]

另一种转置矩阵(将列移动到行)的方法是使用zip() function将所有行作为单独的参数应用,并使用*<expression>调用语法:

def rotateImage(a):
    return [list(r) for r in zip(*reversed(a))]

这仍然使用列表推导,因为zip()生成可迭代对象,而不是列表,每次迭代时都会得到一个元组。上面的列表理解将整个结果转换回列表列表。

如果您想要到位,我建议您阅读Jack在使用Python旋转矩阵时所写的非常出色的答案;他们对如何编码的解释是首屈一指的:How do you rotate a two dimensional array?

答案 1 :(得分:0)

a=a[::-1]只是反过来了。列表理解是:

res = []
for i in range(cols):
    tmp = []
    for m in a:
        tmp.append(m[i])
    res.append(tmp)
return res

**** **** EDIT

这里基本上发生的是每个列索引i算法遍历所有行m(从最后到第一个)并附加m[i](第i个)第{m行中的值)到tmp,然后作为一行附加到res。因此,每个反向列都会作为一行添加到res

所以对于像:

这样的矩阵
1 2 3 4
5 6 7 8
9 1 0 4

第一个内循环迭代将导致tmp=[9, 5, 1]