Home > Mobile >  How to dynamically slice array without eval?
How to dynamically slice array without eval?

Time:12-29

I am in a situation where I need to dynamically slice an array of variable shape/ dimension. So I assemble a string to access it.

This works fine when accessing the data.

some_data = eval("arr[:,[ci]]")

#or

some_data = eval("arr[:,[ci],:]")

#or

some_data = eval("arr[:,:,:,[ci]]")

#etc.

But the limitations of eval() prevent me from assigning using this approach.

eval("arr[:,[ci]]") = some_data

Is there a way I can slice without eval()?

CodePudding user response:

In Python, the indexing operation for a type is implemented by the __getitem__/__setitem__/__delitem__ magic methods. To understand how indexing syntax is interpreted, and thus how these methods are called, we can simply define our own class:

class test:
    def __getitem__(self, idx):
        return idx

test()[:, [1,2,3], ...]
# result: (slice(None, None, None), [1, 2, 3], Ellipsis)

This slice type is a built-in type mentioned earlier in the same documentation, with a link to more specific information.

Ellipsis is simply the name of the object created by the literal syntax .... It's what Numpy uses to represent the complete extent of any number of axes - so this lets us avoid worrying about the dimensionality of the array we're working with.

The important thing to realize is that we can use that same index tuple directly, to get the same result.

Thus, given a dimension along which to slice with [ci], we can construct the necessary tuple, and index with it:

all = slice(None)
def make_index(ci, dimension):
    return (all,) * dimension   ([ci], Ellipsis)

# Now we can do things like:
arr[make_index(ci, dimension)] = some_data
  • Related