on slices, negative indices, which are the equivalent procedures?

Boris Dorestand bdorestand at example.com
Fri Aug 6 13:31:26 EDT 2021


Jach Feng <jfong at ms4.hinet.net> writes:

>> >>>>> s = "Jack Brandom" 
>> >>>>> s[3 : -13 : -1] 
>> >> 'kcaJ' 
>> >> I have no idea how to replace that -13 with a positive index. Is it 
>> >> possible at all? 
> That's not possible because a positive index is relative to the leftmost item 0

And the middle index is always exclusive, so we can't go to the left of
0 and remain positive.  Okay, I think that answers it.  It's not
possible at all.

> Below is some rules of slice usage which I collected sometimes ago.
> -----
> slice s[i:j:k]
>      The result is from start index i to stop index j (excluded) in step k (default is 1).  i, j, k can be positive or negative. For example:  s = [1,  2,  3,  4,  5]
> 1. Positive index is relative to the leftmost item (0), negative index is relative to the rightmost item (-1). Note: out-of-range index is valid.
>        s[-4:5] == s[1:5] == [2,3,4,5]  # index 5 is out-of-range
>        s[4:-6:-1] == [5,4,3,2,1]  # index -6 is out-of-range
> 2. The default index of i and j (When index is omitted) was decided by the sign of k. 
>     For positive k, the start index is 0 (the leftmost item) and the stop index is the one after the rightmost item.
>        s[:3] == s[0:3] == [1,2,3]
>        s[1:] == s[1:5] == [2,3,4,5]
>    For negative k, the start index is -1 (the rightmost item) and the stop index is one ahead of the leftmost item 
>        s[:2:-1] == s[-1:2:-1] == [5,4]
>        s[3::-1] == s[3:-6:-1] == [4,3,2,1]
> 3. The items pick-up order was decided by the sign of k. For positive k, the direction is toward the right. For negative k, it is toward the left.
>     s[1:4] == [2,3,4]
>     s[3:0:-1] == [4,3,2]
> 4. Invalid slice will return an empty []
>     s[2:0] == []

Thank you.  This helped a bit more.  So now I propose the following
simulation.  Can anyone simplify this?  Thanks!

--8<---------------cut here---------------start------------->8---
def mySlice(it, beg, end, step = 1):
  """Simulates Python slices."""
  if step is None: 
    step = 1
  assert step != 0, "step = 0 not allowed"
  ret = []
  cur = beg
  if step > 0:
    return mySlicePositiveStep(it, beg, end, step)
  else:
    return mySliceNegativeStep(it, beg, end, step)

def mySliceNegativeStep(it, beg, end, step = -1):
  """Assume STEP is always negative.  The difference between positive
and neative step is that it reverts the orientation of the loop, but the
loop always begins at BEG, never at END.
  """
  ret = []
  if beg == None:
    beg = -1
  if end == None:
    end = -len(it) - 1
  if beg >= 0: # how to translate positive indices to negative ones
    beg = -len(it) + beg
  if end >= 0:
    end = -len(it) + end
  cur = beg # begin here
  while cur > end: # stop as soon as you arrive at END
    ret.append(it[cur])
    cur += step
  return ret

def mySlicePositiveStep(it, beg, end, step = 1):
  """Assume STEP is always positive.  But if BEG or END are
negative, we apply the equivalence rule BEG == LEN(IT) + BEG.  
For example, if BEG is -1 and LEN(IT) == 10, then BEG is
equivalent to 9 == 10 + -1.  (Similarly for END.)
  """
  ret = []
  if beg == None:
    beg = 0
  if end == None:
    end = len(it)
  if beg < 0:
    beg = len(it) + beg
  if end < 0:
    end = len(it) + end
  cur = beg
  while cur < end:
    ret.append(it[cur])
    cur += step
  return ret
--8<---------------cut here---------------end--------------->8---


More information about the Python-list mailing list