I have a function within a Python (2.7) class that should retrieve the values of the 'cells' around it in a 2 dimensional numpy array. If the index is out of range, I would the value should be set as None.
I'm struggling to find a way to do this without writing 8 try/catch statements, or without using multiple if x else None statements as is in my code below. While they would both work, they don't seem very well structured, and I'm thinking there must be a simpler way to do this - I'm probably caught thinking about this in entirely the wrong way. Any help would be much appreciated.
# This will return a dictionary with the values of the surrounding points
def get_next_values(self, column, row):
if not (column < self.COLUMNS and row < self.ROWS):
print "Invalid row/column."
return False
nextHorizIsIndex = True if column < self.COLUMNS - 2 else False
nextVertIsIndex = True if row < self.ROWS - 2 else False
n = self.board[column, row-1] if column > 0 else None
ne = self.board[column+1, row-1] if nextHorizIsIndex else None
e = self.board[column+1, row] if nextHorizIsIndex else None
se = self.board[column+1, row+1] if nextHorizIsIndex and nextVertIsIndex else None
s = self.board[column, row+1] if nextVertIsIndex else None
sw = self.board[column-1, row+1] if nextVertIsIndex else None
w = self.board[column-1, row] if row > 0 else None
nw = self.board[column-1, row-1] if 0 not in [row, column] else None
# debug
print n, ne, e, se, s, sw, w, nw
To test array for NaN, use the numpy. isnan() method in Python Numpy. Returns True where x is NaN, false otherwise. This is a scalar if x is a scalar.
In numpy, we can check that whether none of the elements of given array is zero or not with the help of numpy. all() function. In this function pass an array as parameter. If any of one element of the passed array is zero then it returns False otherwise it returns True boolean value.
Here is a standard trick: Create your board with an edge padded with the value None. Then you can access any inner 3x3 square and fill in the appropriate values with
nw, n, ne, w, _, e, sw, s, se = (self.board[column-1:column+2, row-1:row+2]).ravel()
For example,
import numpy as np
board = np.empty((10,10), dtype = 'object')
board[:,:] = None
board[1:9, 1:9] = np.arange(64).reshape(8,8)
print(board)
# [[None None None None None None None None None None]
# [None 0 1 2 3 4 5 6 7 None]
# [None 8 9 10 11 12 13 14 15 None]
# [None 16 17 18 19 20 21 22 23 None]
# [None 24 25 26 27 28 29 30 31 None]
# [None 32 33 34 35 36 37 38 39 None]
# [None 40 41 42 43 44 45 46 47 None]
# [None 48 49 50 51 52 53 54 55 None]
# [None 56 57 58 59 60 61 62 63 None]
# [None None None None None None None None None None]]
column = 1
row = 1
nw, n, ne, w, _, e, sw, s, se = (board[column-1:column+2, row-1:row+2]).ravel()
print(nw, n, ne, w, _, e, sw, s, se)
# (None, None, None, None, 0, 1, None, 8, 9)
Note that
print(board)
that is the way the values are formatted. So perhaps you want board[row-1:row+2, column-1:column+2]
instead. Of course, you could define your own print_board
function, and then be free to use whatever convention you like.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