Testing if an index is in a slice

Bryan Olson fakeaddress at nowhere.org
Sat Jan 3 17:53:12 EST 2009


ajaksu wrote:
> On Jan 1, 4:12 pm, mma... at gmx.net wrote:
>> I would like to check if an index is in a slice or not without
>> iterating over the slice.
>>
>> Something like:
>>
>>>>> isinslice(36, slice(None, 34, -1))
>> True
> 
> I think it'd be feasible for slices that can be mapped to ranges[1],
> but slices are more flexible than that.

If we add a parameter for the length of the list to which the slice is 
applied, then inslice() is well-defined.

I thought it would easy to write, but that was hours ago when I knew 
less about Python slice indexing than I do now. And I thought I new a 
bunch from writing a virtual slice class.

I'm leaning towards mmanns' idea that this should be built in. Handling 
all the cases is remarkably tricky. Here's a verbose version, with a 
little test:


def inslice(i, slc, length):
     """ Would index i be part of slice slc of a list of len length?
     """

     step = slc.step or 1

     if step > 0:

         if slc.start is None:
             start = 0
         elif slc.start >= 0:
             start = slc.start
         else:
             start = max(0, length + slc.start)

         if slc.stop is None:
             stop = length
         elif slc.stop >= 0:
             stop = min(length, slc.stop)
         else:
             stop = length + slc.stop

         return start <= i < stop and (i - start) % step == 0

     else:

         if slc.start is None:
             start = length - 1
         elif slc.start >= 0:
             start = min(length - 1, slc.start)
         else:
             start = length + slc.start

         if slc.stop is None:
             stop = -1
         elif slc.stop >= 0:
             stop = slc.stop
         else:
             stop = max(-1, length + slc.stop)

         return start >= i > stop and (start - i) % (-step) == 0



# test
for start in [None, 0, 1, -1, -3, 4]:
     for stop in [None, 0, 1, -1, 3, -5]:
         for step in [None, 1, -1, 2, -3]:
             for n in [0, 1, 2, 3, 5, 11, 16]:
                 slc = slice(start, stop, step)
                 s1 = [i for i in range(-3, n + 5) if inslice(i, slc, n)]
                 s2 = sorted(range(n)[slc])
                 assert s1 == s2



-- 
--Bryan



More information about the Python-list mailing list