The rot90() function is used to rotate an array by 90 degrees in the plane specified by axes. Rotation direction is from the first towards the second axis. Array of two or more dimensions. Number of times the array is rotated by 90 degrees.
Rotate Matrix 90 Degree Clockwise or Right Rotation The rotation of a matrix involves two steps: First, find the transpose of the given matrix. Swap the elements of the first column with the last column (if the matrix is of 3*3). The second column remains the same.
That's a clever bit.
First, as noted in a comment, in Python 3 zip()
returns an iterator, so you need to enclose the whole thing in list()
to get an actual list back out, so as of 2020 it's actually:
list(zip(*original[::-1]))
Here's the breakdown:
[::-1]
- makes a shallow copy of the original list in reverse order. Could also use reversed()
which would produce a reverse iterator over the list rather than actually copying the list (more memory efficient).*
- makes each sublist in the original list a separate argument to zip()
(i.e., unpacks the list)zip()
- takes one item from each argument and makes a list (well, a tuple) from those, and repeats until all the sublists are exhausted. This is where the transposition actually happens.list()
converts the output of zip()
to a list.So assuming you have this:
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
You first get this (shallow, reversed copy):
[ [7, 8, 9],
[4, 5, 6],
[1, 2, 3] ]
Next each of the sublists is passed as an argument to zip
:
zip([7, 8, 9], [4, 5, 6], [1, 2, 3])
zip()
repeatedly consumes one item from the beginning of each of its arguments and makes a tuple from it, until there are no more items, resulting in (after it's converted to a list):
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
And Bob's your uncle.
To answer @IkeMiguel's question in a comment about rotating it in the other direction, it's pretty straightforward: you just need to reverse both the sequences that go into zip
and the result. The first can be achieved by removing the [::-1]
and the second can be achieved by throwing a reversed()
around the whole thing. Since reversed()
returns an iterator over the list, we will need to put list()
around that to convert it. With a couple extra list()
calls to convert the iterators to an actual list. So:
rotated = list(reversed(list(zip(*original))))
We can simplify that a bit by using the "Martian smiley" slice rather than reversed()
... then we don't need the outer list()
:
rotated = list(zip(*original))[::-1]
Of course, you could also simply rotate the list clockwise three times. :-)
Consider the following two-dimensional list:
original = [[1, 2],
[3, 4]]
Lets break it down step by step:
>>> original[::-1] # elements of original are reversed
[[3, 4], [1, 2]]
This list is passed into zip()
using argument unpacking, so the zip
call ends up being the equivalent of this:
zip([3, 4],
[1, 2])
# ^ ^----column 2
# |-------column 1
# returns [(3, 1), (4, 2)], which is a original rotated clockwise
Hopefully the comments make it clear what zip
does, it will group elements from each input iterable based on index, or in other words it groups the columns.
There are three parts to this:
Just an observation. The input is a list of lists, but the output from the very nice solution: rotated = zip(*original[::-1]) returns a list of tuples.
This may or may not be an issue.
It is, however, easily corrected:
original = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
def rotated(array_2d):
list_of_tuples = zip(*array_2d[::-1])
return [list(elem) for elem in list_of_tuples]
# return map(list, list_of_tuples)
print(list(rotated(original)))
# [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
The list comp or the map will both convert the interior tuples back to lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With