简体   繁体   English

旋转图像列表理解

[英]rotate Image List comprehension

While solving a problem on matrix rotation I came across a solution .The question asks to rotate the matrix by 90 degrees 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)]

Can someone help me in breaking down this list comprehension to regular for-loop and understand the flow of the program 有人可以帮助我将列表理解分解为常规的for循环并了解程序的流程吗

You have a nested list comprehension, an outer list comprehension creating a new list for every iteration. 您有一个嵌套列表理解,一个外部列表理解为每次迭代创建一个新列表。

You can deconstruct any list comprehension by reading the for and if components from left to right as nested blocks. 您可以通过读取forif组件从左到右作为嵌套块来解构任何列表理解。 Everything before the first for is the expression that produces the elements of the list. 第一个for之前的所有内容都是产生列表元素的表达式。

So the basic structure is: 因此,基本结构为:

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

which can always be converted to a regular loop with: 始终可以使用以下命令将其转换为常规循环:

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

I added in _result as an explicit name for the list that is produced; 我添加了_result作为所生成列表的显式名称。 note that the result of <expression> is appended to it each iteration. 请注意,每次迭代都会将<expression>的结果附加到它的后面。

Your example breaks down to two list comprehensions. 您的示例分为两个列表理解。 The outer loop is this: 外循环是这样的:

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

So the [m[i] for m in a] is the expression here! 因此[m[i] for m in a]是这里的表达式! Writing this out that becomes: 将其写为:

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

The inner list comprehension is straightforward: 内部列表的理解很简单:

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

If you put these two together you get: 如果将这两部分放在一起,您将获得:

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

Now you can see that the i target from the outer loop, is used each time in the inner loop. 现在您可以看到,每次在内部循环中都使用外部循环中的i目标。 Because i loops over the number of columns, but m is a row, this produces first a list with all the values from the very first column, then the second column, and then the third, etc. 因为i遍历了列数,但是m是一行,所以这首先生成一个列表,其中包含第一列的所有值,然后是第二列,然后是第三列,依此类推。

The line before the list comprehension reversed the rows: 列表理解之前的那一行使反转

a = a[::-1]

This takes all rows, and goes from the last to the first (stepping backwards, with a -1 step size). 这将占用所有行,并从最后一行到第一行(向后退,步长为-1 )。 This makes it so that the list comprehension loops over the rows in reverse order. 这样可以使列表理解以相反的顺序遍历行。

The code can be cleaned up and improved a little. 该代码可以清理和改进一点。 The rows variable is never used, for example, and we can use the reversed() function to loop over a list in reverse order without creating a copy: 例如,从不使用rows变量,我们可以使用reversed()函数以相反的顺序遍历列表,而无需创建副本:

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

Another method of transposing a matrix (moving columns to rows) is using the zip() function with all the rows applied as separate arguments, with the *<expression> call syntax: 转换矩阵(将列移动到行)的另一种方法是使用zip()函数,其中所有行都应用为单独的参数,并带有*<expression>调用语法:

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

This still uses a list comprehension, because zip() produces an iterable object , not a list, and each time you iterate you get a tuple. 这仍然使用列表推导,因为zip()会生成一个可迭代的对象 ,而不是列表,并且每次迭代时都会得到一个元组。 The above list comprehension converts the whole result back to a list of lists. 上面的列表理解将整个结果转换回列表列表。

If you want to do this in place , I suggest you read the very excellent answer Jack wrote on rotating a matrix with Python; 如果您想就地执行此操作,建议您阅读Jack关于用Python旋转矩阵的出色回答。 their explanation of how to code this is second to none: How do you rotate a two dimensional array? 他们对如何编码的解释是首屈一指的: 如何旋转二维数组?

The a=a[::-1] is simply a in reverse. a=a[::-1]只是一个反向。 The list comprehension is: 列表理解为:

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

****EDIT**** ****编辑****

What is basically happening here is the for each column index i the algorithm goes through all the rows m (form last to first) and appends the m[i] (the i'th value in the m'th row) to tmp , which is then appended as a row, to res . 基本上,这里发生的是对于每个列索引i ,算法遍历所有行m (从最后到第一),并将m[i] (第m行中的第i个值)附加到tmp ,然后作为行附加到res So each reversed column is added as a row to res . 因此,每个反向列都作为一行添加到res

So for a matrix like: 因此,对于像这样的矩阵:

1 2 3 4
5 6 7 8
9 1 0 4

The first inner loop iteration will result in tmp=[9, 5, 1] 第一次内部循环迭代将导致tmp=[9, 5, 1]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM