3

I'm building a basic mapping robot where all the data is stored on a 2D python array. However I am unable to find any way to move entire rows or columns over and then insert a blank row/column in. For example:

['#','0','0']        
['0','1','0']                                            
['#','0','0']

if moved to the right to look like :

['0','#','0']        
['0','0','1']                                            
['0','#','0']

or

['#','0','#']         
['0','1','0']                                     
['0','0','0']                                     

if moved down to look like :

['0','0','0']         
['#','0','#']                                     
['0','1','0']

I have already figured out how to expand the array whenever something is detected outside of the pre-defined array however I am unable to move rows and columns like demonstrated above.

Any help would be greatly appreciated. Thanks :)

4 Answers 4

3

Have you looked at numpy and numpy.roll for this?

import numpy as np
a = np.array([['#','0','0'],
['0','1','0'],                                           
['#','0','0']])

then you can shift right:

a = np.roll(a,1)
a[:,0] = 0

shift left:

a = np.roll(a,-1)
a[:,-1] = 0

shift up:

a = np.roll(a,-1,axis = 0)
a[-1,:] = 0

shift down:

a = np.roll(a,1,axis = 0)
a[0,:] = 0
Sign up to request clarification or add additional context in comments.

Comments

2

The numpy solutions work great, but here is a solution in pure Python, with no imports. Note that most of this code just prints the results--each roll uses only one line of code. I also added shiftedup, where the matrix is rotated up then the last row is replaced with all zeros (though it is done more efficiently than that).

myarray = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
print('\nOriginal:')
for row in myarray:
    print(row)

rolledup = myarray[1:] + myarray[:1]
print('\nRolled up:')
for row in rolledup:
    print(row)

rolleddown = myarray[-1:] + myarray[:-1]
print('\nRolled down:')
for row in rolleddown:
    print(row)

rolledleft = [row[1:] + row[:1] for row in myarray]
print('\nRolled left:')
for row in rolledleft:
    print(row)

rolledright = [row[-1:] + row[:-1] for row in myarray]
print('\nRolled right:')
for row in rolledright:
    print(row)

shiftedup= myarray[1:] + [[0] * len(myarray[0])]
print('\nShifted up:')
for row in shiftedup:
    print(row)

The printout from that is:

Original:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

Rolled up:
[4, 5, 6]
[7, 8, 9]
[1, 2, 3]

Rolled down:
[7, 8, 9]
[1, 2, 3]
[4, 5, 6]

Rolled left:
[2, 3, 1]
[5, 6, 4]
[8, 9, 7]

Rolled right:
[3, 1, 2]
[6, 4, 5]
[9, 7, 8]

Shifted up:
[4, 5, 6]
[7, 8, 9]
[0, 0, 0]

4 Comments

Do you know of anyway of having the numbers at the top replace to the bottom but to replace then with a row of zero's instead. i.e: [1,2,3][4,5,6][7,8,9] becomes [4,5,6][7,8,9][0,0,0]
@user9015687: See the additions to my code and the printout.
Thanks that is working perfectly. I'm a bit confused with the use of colons in manipulating the arrays, I've seen them all over the place but I don't really understand them. You wouldn't be able to tell me what they mean could you. Thanks
@user9015687: That is Python's slice notation. Start with this answer on this site and the official tutorial, and if you still do not understand slices, do a web search on "python slice." Those explain better than I could.
1

You can create a class to handle this movements like this:

class Board(object):
    def __init__(self, rows):
        self.rows = rows
        self.print_status()

    def print_status(self):
        for row in self.rows:
            print(row)

    def right(self):
        new_rows = []
        for row in self.rows:
            row = row[-1:] + row[:len(row)-1]
            new_rows.append(row)
        self.rows = new_rows
        self.print_status()

    def left(self):
        new_rows = []
        for row in self.rows:
            row = row[1:] + row[:1]
            new_rows.append(row)
        self.rows = new_rows
        self.print_status()

    def up(self):
        new_rows = []
        for row in self.rows[1:]:
            new_rows.append(row)
        new_rows.append(self.rows[0])
        self.rows = new_rows
        self.print_status()

    def down(self):
        new_rows = []
        new_rows.append(self.rows[-1])
        for row in self.rows[:-1]:
            new_rows.append(row)
        self.rows = new_rows
        self.print_status()

Example:

>>> a = Board([[1,2,3],[4,5,6],[7,8,9]])
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

>>> a.down()
[7, 8, 9]
[1, 2, 3]
[4, 5, 6]

>>> a.up()
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

>>> a.right()
[3, 1, 2]
[6, 4, 5]
[9, 7, 8]

Comments

0

This can be easily done by "roll" function from numpy
example in your case:

import numpy as np
a = np.array([['#','0','0'], ['0','1','0'], ['#','0','0']])

output will be:

array([['#', '0', '0'],
   ['0', '1', '0'],
   ['#', '0', '0']], dtype='<U1')

for 1st usecase:

np.roll(a, 1, 1)

output will be

array([['0', '#', '0'],
   ['0', '0', '1'],
   ['0', '#', '0']], dtype='<U1')

for second case yo can simply take transpose:

a.T

and output will be

array([['#', '0', '#'],
   ['0', '1', '0'],
   ['0', '0', '0']], dtype='<U1')

Third case be done by applying numpy roll operation on transpose matrix

np.roll(a.T, 1, 0)

output

array([['0', '0', '0'],
   ['#', '0', '#'],
   ['0', '1', '0']], dtype='<U1')

1 Comment

roll alone doesn't insert blank rows, it simply takes from the other side of the array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.