2021/11/19

Using SubSlicing in Python passing "Slice Spec" as a string

Python's implicit [start:end:step] notation makes slicing objects very easy.

But if you want to create a function that accepts optional params that allow you to manipulate the return then your left to create your own interface specifying how to slice the return data.

In the sample below two params are passed to tester

theList - A list object to be sliced
sliceSpec - a string specifying the python slice notation

Python provides a helper called "slice" which accepts three params (start, end, step) which are the components of an implied slice.

But given that 0 (zero) is a legitimate value for any of the arguments when an argument is skipped ":5" the missing must be represented as a "None"

Also the values passed to slice() must be integers and split() will return a list of strings

So the below example takes "sliceSpec" does the following

  1. if sliceSpec is None, then replace with an empty string
        otherwise split(":") fails
  2. Traverse the list returned by split()
    • substitute blank strings with None
    • convert any values to integers
  3. Pass the transformed results from split() into arguments passed to slice()
  4. use the slice operator to access the subList from "theList"

Example Code

def tester(theList, sliceSpec=None):

    returnList = theList[slice(*(int(i) if i != '' else None for i in (sliceSpec or str()).split(":")))]

    print(f"'{sliceSpec}' = {returnList}\n")


mylist = [ 1,2,3,4,5,6,7,8,9 ]

tester(mylist)
tester(mylist, None)
tester(mylist, "")
tester(mylist, ":5")
tester(mylist, "0:1")
tester(mylist, ":1")
tester(mylist, "1:-2")
tester(mylist, "::-1")

Results

$ python3 test

'None' = [1, 2, 3, 4, 5, 6, 7, 8, 9]

'None' = [1, 2, 3, 4, 5, 6, 7, 8, 9]

'' = [1, 2, 3, 4, 5, 6, 7, 8, 9]

':5' = [1, 2, 3, 4, 5]

'0:1' = [1]

':1' = [1]

'1:-2' = [2, 3, 4, 5, 6, 7]

'::-1' = [9, 8, 7, 6, 5, 4, 3, 2, 1]

 

 

No comments: