12

I have a list of list and I need to rotate it ninety degrees. I managed to get the first new row but I couldn't get any of the others so I put the for loop in to a a function and I increased the count by one every iteration but I've just had big mess printed to the terminal.

grid = [['.', '.', '.', '.', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['0', '0', '0', '0', '0', '.'],
        ['.', '0', '0', '0', '0', '0'],
        ['0', '0', '0', '0', '0', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['.', '.', '.', '.', '.', '.']]

How I need to rotate.

'''
..00.00..
.0000000.
.0000000.
..00000..
...000...
....0....

'''

My code

def get_row(grid, new_grid, new_row, count):
    for row in grid:
        new_row.append(row[count])
    new_grid.append(new_row)

new_grid = []
new_row = []
count = 0

for x in range(0, 6):
    count = 0
    get_row(grid, new_grid, new_row, count)
    count +=1

for row in new_grid:
    print row
  • 2
    FYI, [How do you rotate a two dimensional array?](http://stackoverflow.com/q/42519/364696) covers just about every language, [including Python](http://stackoverflow.com/a/24356420/364696). – ShadowRanger Dec 18 '15 at 01:30
  • 1
    Oh, and [Rotating a two-dimensional array in Python](http://stackoverflow.com/q/8421337/364696) is probably even better targeted; it covers both the how and the why. Also, [this answer to How do you rotate a two dimensional array?](http://stackoverflow.com/a/496056/364696) is a better link, since it uses `zip`, not `map(None` which is weird and not portable to Py3. – ShadowRanger Dec 18 '15 at 01:43

4 Answers4

17

You can rotate your list of lists 90° using zip(*reversed(your_list)) like this:

grid = [['.', '.', '.', '.', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['0', '0', '0', '0', '0', '.'],
        ['.', '0', '0', '0', '0', '0'],
        ['0', '0', '0', '0', '0', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['.', '.', '.', '.', '.', '.']]

print("\n".join(map("".join, zip(*reversed(grid)))))

Out:

..00.00..
.0000000.
.0000000.
..00000..
...000...
....0....

Instead of reversed(grid) you can use grid[::-1] which also reverses the outer list, except it creates a copy of your list, which uses more memory (here I'm also using pprint to show you what exactly your transposed list looks like):

from pprint import pprint
pprint(list(zip(*grid[::-1])))

[('.', '.', '0', '0', '.', '0', '0', '.', '.'),
 ('.', '0', '0', '0', '0', '0', '0', '0', '.'),
 ('.', '0', '0', '0', '0', '0', '0', '0', '.'),
 ('.', '.', '0', '0', '0', '0', '0', '.', '.'),
 ('.', '.', '.', '0', '0', '0', '.', '.', '.'),
 ('.', '.', '.', '.', '0', '.', '.', '.', '.')]

Which if you really wanted lists instead of tuples you could convert them back to list:

pprint([list(row) for row in zip(*reversed(grid))])

[['.', '.', '0', '0', '.', '0', '0', '.', '.'],
 ['.', '0', '0', '0', '0', '0', '0', '0', '.'],
 ['.', '0', '0', '0', '0', '0', '0', '0', '.'],
 ['.', '.', '0', '0', '0', '0', '0', '.', '.'],
 ['.', '.', '.', '0', '0', '0', '.', '.', '.'],
 ['.', '.', '.', '.', '0', '.', '.', '.', '.']]
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Now that we have python3, for simple print of arrays, instead of using `print('\n'.join(array))` I now usually use `print(*array,sep='\n')` – RufusVS Jan 23 '21 at 21:15
4

index magic:

>>> grid = [['.', '.', '.', '.', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['0', '0', '0', '0', '0', '.'],
        ['.', '0', '0', '0', '0', '0'],
        ['0', '0', '0', '0', '0', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['.', '.', '.', '.', '.', '.']]
>>> for i in range(len(grid[0])): #assuming they all have the same length
    print (''.join(x[i] for x in grid))


..00.00..
.0000000.
.0000000.
..00000..
...000...
....0....

or to save to a new grid:

>>> newgrid = []
>>> for i in range(len(grid[0])): #assuming they all have the same length
    newgrid.append([x[i] for x in grid])


>>> newgrid
[['.', '.', '0', '0', '.', '0', '0', '.', '.'],
 ['.', '0', '0', '0', '0', '0', '0', '0', '.'],
 ['.', '0', '0', '0', '0', '0', '0', '0', '.'],
 ['.', '.', '0', '0', '0', '0', '0', '.', '.'],
 ['.', '.', '.', '0', '0', '0', '.', '.', '.'],
 ['.', '.', '.', '.', '0', '.', '.', '.', '.']]

or one line:

>>> newgrid = [[x[i] for x in grid] for i in range(len(grid[0]))]
>>> newgrid
[['.', '.', '0', '0', '.', '0', '0', '.', '.'],
 ['.', '0', '0', '0', '0', '0', '0', '0', '.'],
 ['.', '0', '0', '0', '0', '0', '0', '0', '.'],
 ['.', '.', '0', '0', '0', '0', '0', '.', '.'],
 ['.', '.', '.', '0', '0', '0', '.', '.', '.'],
 ['.', '.', '.', '.', '0', '.', '.', '.', '.']]
R Nar
  • 5,465
  • 1
  • 16
  • 32
  • 1
    This answer is wrong. Instead of just rotating the image it transposes it (meaning it rotates and then **mirrors it**). It just looks right in this case because the image is symmetrical. – Boris Verkhovskiy Dec 28 '19 at 07:30
1

numpy.rot90 can do that and is fast for large matrices such as images:

import numpy as np

grid = [['.', '.', '.', '.', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['0', '0', '0', '0', '0', '.'],
        ['.', '0', '0', '0', '0', '0'],
        ['0', '0', '0', '0', '0', '.'],
        ['0', '0', '0', '0', '.', '.'],
        ['.', '0', '0', '.', '.', '.'],
        ['.', '.', '.', '.', '.', '.']]
grid = np.rot90(grid, k=3)   
print(grid)

# [['.' '.' '0' '0' '.' '0' '0' '.' '.']
#  ['.' '0' '0' '0' '0' '0' '0' '0' '.']
#  ['.' '0' '0' '0' '0' '0' '0' '0' '.']
#  ['.' '.' '0' '0' '0' '0' '0' '.' '.']
#  ['.' '.' '.' '0' '0' '0' '.' '.' '.']
#  ['.' '.' '.' '.' '0' '.' '.' '.' '.']]
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
101
  • 8,514
  • 6
  • 43
  • 69
1

It's actually easier to do this with a one dimensional array than it is with a 2D array (edit: I was wrong, the zip approach is pretty darn easy too, and the best IMO; leaving this for comparison), so just for fun, we'll convert to 1D, than rotate to a new 2D:

>>> from itertools import chain
>>> # Collapses to 1D
>>> grid1d = list(chain(*grid))
>>> # Rotates and rebuilds as 2D
>>> numcolumns = len(grid[0])
>>> rotated = [grid1d[i::numcolumns] for i in range(numcolumns)]
>>> print(*rotated, sep="\n")
['.', '.', '0', '0', '.', '0', '0', '.', '.']
['.', '0', '0', '0', '0', '0', '0', '0', '.']
['.', '0', '0', '0', '0', '0', '0', '0', '.']
['.', '.', '0', '0', '0', '0', '0', '.', '.']
['.', '.', '.', '0', '0', '0', '.', '.', '.']
['.', '.', '.', '.', '0', '.', '.', '.', '.']

Side-note: If you're on Python 2, that print syntax would require a from __future__ import print_function to work.

Community
  • 1
  • 1
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271