4

Suppose I have a variable S with the string "1:3" (or for that matter, "1", or "1:" or ":3") and I want to use that as a slice specifier on list L. You cannot simply do L[S] since the required args for a slice are "int:int".

Now, I current have some ugly code that parses S into its two constituent ints and deals with all the edge cases (4 of them) to come up with the correct slice access but this is just plain ugly and unpythonic.

How do I elegantly take string S and use it as my slice specifier?

Pedro Romano
  • 10,973
  • 4
  • 46
  • 50
staggart
  • 267
  • 1
  • 6
  • 15

2 Answers2

5

This can be done without much hacking by using a list comprehension. We split the string on :, passing the split items as arguments to the slice() builtin. This allows us to quite nicely produce the slice in one line, in a way which works in every case I can think of:

slice(*[int(i.strip()) if i else None for i in string_slice.split(":")])

By using the slice() builtin, we neatly avoid having to deal with too many edge cases ourselves.

Example usage:

>>> some_list = [1, 2, 3]
>>> string_slice = ":2"
>>> some_list[slice(*[int(i.strip()) if i else None for i in string_slice.split(":")])]
[1, 2]
>>> string_slice = "::-1"
>>> some_list[slice(*[int(i.strip()) if i else None for i in string_slice.split(":")])]
[3, 2, 1]
Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • Much better to use split here over partition as I did to allow for the third arg. – sberry Nov 10 '12 at 18:08
  • Indeed, it works nicely. This one also works quite nicely at giving you decent errors for incorrect input (by complaining about extra operands to ``slice()``). – Gareth Latty Nov 10 '12 at 18:12
  • While this solution works, I think vivek's is much cleaner and easier to understand - something important for when someone takes over my code. – staggart Nov 11 '12 at 02:27
1

Here's another solution

eval("L[%s]" % S) 

warning - It's not safe if S is coming from an external(unreliable) source.

vivek
  • 4,951
  • 4
  • 25
  • 33