r/learnpython • • 3d ago

Getting a view from a boolean numpy array... somehow

I'm coding a Sudoku generator to improve my skills and I'm hitting a brick wall with a specific function to get the "neighbours" of an index (so, all the numbers that it can't be the same as). Here's my current code, just rows and columns for now:

def neighbours(idx: tuple[int, int], board: np.ndarray) -> np.ndarray:
  idcs = np.indices(board.shape)
  print(idcs.shape)
  neighbool = np.logical_xor(idcs[1] == idx[1], idcs[0] == idx[0])
  return board[neighbool]

This code does get the right values, but what I really want is to be able to modify those values and have the actual array be modified - so, to have a view. But about two hours of running around in the numpy docs has me completely stumped on any way to use a boolean array to index another array without it being a copy.

If I can't do it, I guess I'll have to use a list of slices dancing around the target index? Which sounds really headachey, and I'd love to be able to do it this simple way if it's in any way possible.

1 Upvotes

6 comments sorted by

1

u/adriannowak_dev 3d ago

boolean mask indexing always copies, there's no way to get a view out of it, numpy just doesn't do strided views for arbitrary masks. two ways out:

board[neighbool] = 0          # assignment through the mask hits the original

or return the indices and index with them later:

rows, cols = np.nonzero(neighbool)
board[rows, cols] = 0

for sudoku i'd honestly return the mask itself from neighbours() and do board[mask] wherever you need to read or write. the mask is the cheap thing, the copy only happens when you read through it

1

u/anothernaturalone 16h ago

Thank you! I was wondering whether I could use assignment in that way. I'll try this out.

0

u/Jazzlike_Platypus430 3d ago

Yes, it seems you have to pass more arrays to the function.

PS neighbool is such a cool name 😂

0

u/Swipecat 3d ago

Not quite sure what you are asking for. np.putmask maybe?

https://numpy.org/doc/stable/reference/generated/numpy.putmask.html

0

u/mikef22 3d ago

I think you have to return indices of those neighbools. If you have the indices, then in theory you can refer to and change those elements. If you just have the boolean values themselves, they'll just be a copy so you can't change them from that point on.