0

I have a function that takes in a slice. What I want to do is to check if the end value in this slice is equal to -1. If that is the case, I want to reset the slice to another value. I can't find supporting documentation and do not know how to proceed.

datalist=[None, 'Grey', 'EE20-700', 'EE-42-01', 'EE15-767', 'EE0-70650', 'B&B', 1, 1, 1, 1, 1, '300R', True, 'Nov. 2, 2022', 'Nov. 2, 2022', 1, 1, 1, True, 3]

#If we just apply the given slice_dimensions, the following happens:
slice_dimensions=slice(1, -1)
datalist[slice_dimensions]
['Grey', 'EE20-700', 'EE-42-01', 'EE15-767', 'EE0-70650', 'B&B', 1, 1, 1, 1, 1, '300R', True, 'Nov. 2, 2022', 'Nov. 2, 2022', 1, 1, 1, True]

As you can see this is problematic, because the last element of my list (3) is omitted with the current slice dimension. I have seen many solutions saying I should use len(datalist)-1 or something similar instead, but this is not a workable option because the list lengths differ, and I want to keep it simple. If we can just check if end of slice is equal to -1 and change it to None, the problem is solved:

#If we just apply the given slice_dimensions, the following happens:
slice_dimensions=slice(1, None)
datalist[slice_dimensions]
['Grey', 'EE20-700', 'EE-42-01', 'EE15-767', 'EE0-70650', 'B&B', 1, 1, 1, 1, 1, '300R', True, 'Nov. 2, 2022', 'Nov. 2, 2022', 1, 1, 1, True, 3]

I would like to make a function to do so, but do not know how to proceed, something like this:

def slicer(slice_dimensions):
    if slice_dimensions[1] == -1:  #This part I do not know how to proceed
        slice_dimensions= slice(1, None)
    data_of_interest=datalist[slice_dimensions]
    return(data_of_interest)

How should I proceed in doing so?

Rivered
  • 741
  • 7
  • 27
  • Having mixed types in a list is a big red flag - that kind of thing is absolutely more trouble than it's worth. – Edward Peters Nov 22 '22 at 20:10
  • 1
    Don't use `list` as a variable name, it's a built-in type name. – Barmar Nov 22 '22 at 20:12
  • `len(l)-1` can be called on each `list` to always get the correct length - how is that not simple? – Edward Peters Nov 22 '22 at 20:13
  • @Edward Peters, because the list is generated from ```[cell.value for cell in worksheet[i]]``` – Rivered Nov 22 '22 at 20:15
  • 2
    The values of a `slice` object are available as the `start`, `stop`, and `step` attributes. – jasonharper Nov 22 '22 at 20:15
  • 1
    `slicer` looks fine, though you can use `slice_dimensions.stop` as a more self-explanatory version of `slice_dimensions[1]`. It's not clear, though, why you need to second-guess the caller. If they wanted the results of `slice(1, None)`, they could pass that instead of `slice(1, -1)` in the first place. – chepner Nov 22 '22 at 20:15
  • @Barmar, it is an example list, in truth its not called list! – Rivered Nov 22 '22 at 20:16
  • 2
    Don't use it in examples, either. – Barmar Nov 22 '22 at 20:16
  • 1
    What is `<-` supposed to be? Why isn't that just an ordinary `=` assignment? – Barmar Nov 22 '22 at 20:17
  • 1
    Why doesn't `slicer()` take the list as a parameter? It shouldn't be hard-coded to a specific list variable. – Barmar Nov 22 '22 at 20:18
  • 1
    Why is it a problem that the last element is omitted? Isn't that what they wanted when they said `slice_dimensions = slice(1, -1)`? Is the stop value being calculated in a way that might go below zero without wanting it to wrap around? That seems like the place to address this. – Barmar Nov 22 '22 at 20:20
  • I changed ```list``` to ```datalist```... Also, the solution from @chepner with ```slice_dimensions.stop``` seems to be very helpful. @Barmar, I quickly worked this out, have been using too much R, and confused ```<-``` with ```=```, in addition, slicer does take datalist in the actual example. – Rivered Nov 22 '22 at 20:21
  • Does this answer your question? [Python slice how-to, I know the Python slice but how can I use built-in slice object for it?](https://stackoverflow.com/questions/3911483/python-slice-how-to-i-know-the-python-slice-but-how-can-i-use-built-in-slice-ob) – mkrieger1 Nov 22 '22 at 20:22
  • @Barmar, in actuality the datalist comes from a row in an excel form. These are added to Django databases, the row size in the excel can sometimes be longer than the number of columns allowed, and need to be sliced. If the -1 is used as default this is not the case, but then I want to change it to None otherwise the last list item element is omitted. Perhaps I should use len(datalist)-1. – Rivered Nov 22 '22 at 20:26
  • 1
    This just sounds like a bug in whatever thought `-1` was a usable sentinel value. `foo[x:]` equivalent to `foo.__getitem__(slice(x, None))`, not `foo.__getitem__(slice(x, -1))`. – chepner Nov 22 '22 at 20:27
  • 1
    `len(datalist)-1` is equivalent to `-1` in a slice. Why would using that instead make a difference? – Barmar Nov 22 '22 at 20:27

2 Answers2

2

You could define a wrapper for slice(). Something like:

def nonwrapping_slice(start=0, stop=None, stride=1):
    if stop is not None and stop < 0 and stride > 0:
        stop = None
    return slice(start, stop, stride)

Then you can call nonwrapping_slice(1, -1) and it will return slice(1, None, 1)

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

slice object exposes all its parameters as start, stop and step attributes (readonly). So you can just create a new slice, if necessary:

def slicer(objects, slice_dimensions):
    if slice_dimensions.end == -1:
        # Create a copy slice with end replaced with None
        slice_dimensions = slice(slice_dimensions.start, None, slice_dimensions.step)
    return objects[slice_dimensions]

Also, slices have a useful indices method, that takes sequence length as argument and outputs a tuple of actual (start, stop, step) (without None and negative values). You can read more in docs (one screen above this anchor - they do not have own heading with href to an anchor)

STerliakov
  • 4,983
  • 3
  • 15
  • 37