Reputation: 476
Is there a Boolean function to test whether an integer is an index value contained in a slice
object without unpacking the start
, stop
, and step
parameters?
3 in slice(1, 6, 2)
raises an error as slices are not iterable.
The predicate should work for arbitrary None
, start
, stop
, step
parameters. The logic is straightforward but hoping there's a built in or package.
Upvotes: 8
Views: 724
Reputation: 114440
The logic is not as straightforward as you think, since it doesn't make sense to do this for a None
stop or start (depending on the sign of step
), since you need to specify a length.
Essentially, what you are asking for is containment in a range
object, which holds the same information as a slice, but is a valid sequence, and supports fast containment checking. slice
has a method called indices
to help with the transformation, if you provide the length of the sequence you are interested in slicing:
def in_slice(n, s, length):
return n in range(*s.indices(length))
Upvotes: 11
Reputation: 42133
If you can select an appropriately sized range, you can apply the slice to it and determine if the index will be in the range.
for positive/None boundaries, this is merely a matter of having a big enough range to contain the index itself:
i in range(i+1)[slice(start,stop,step)]
3 in range(7)[slice(1,6,2)] --> True
In order to support negative boundaries (in particular a negative start), you'll need to ensure that index offset from start is a multiple of the step and that the size is small enough to include the index. This is under the assumption that there exists a range size that will contain the index. Otherwise you'll have to supply a range size yourself:
def inSlice(i,s, size = None):
if size is None:
step = s.step or 1
start = s.start or 0
size = size or i+1
if step < 0 or start <= 0:
size = (i-min(0,start))//step*step - int(s.stop is None)
return i in range(size)[s]
This will provide the following results:
inSlice( 3 , slice(1, 6, 2) ) --> True ( size = 4 )
inSlice( 37000216 , slice(10, 100000000, 3) ) --> True ( size = 37000217 )
inSlice( 17 , slice(-100, 10, -3) ) --> True ( size = 117 )
inSlice( 17 , slice(-100, -10, 3) ) --> True ( size = 117 )
inSlice( 97 , slice(100, None, -3) ) --> True ( size = 98 )
inSlice( 107 , slice(None, 100, -3) ) --> True ( size = 108 )
inSlice( 97 , slice(-10, None, -3) ) --> True ( size = 107 )
Upvotes: 0