1

Sometime I write code like this:

a,temp,b = s.partition('-')

I just need to pick the first and 3rd elements. temp would never be used. Is there a better way to do this?

In other terms, is there a better way to pick distinct elements to make a new list?

For example, I want to make a new list using the elements 0,1,3,7 from the old list. The code would be like this:

newlist = [oldlist[0],oldlist[1],oldlist[3],oldlist[7]]

It's pretty ugly, isn't it?

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
Max
  • 7,957
  • 10
  • 33
  • 39
  • I don't see how you can make it prettier unless you want to write a function or rename oldlist to something shorter. – Loopo Aug 29 '12 at 03:29

5 Answers5

8

Be careful using

a, _, b = s.partition('-')

sometimes _ is use for internationalization (gettext), so you wouldn't want to accidentally overwrite it.

Usually I would do this for partition rather than creating a variable I don't need

a, b = s.partition('-')[::2]

and this in the general case

from operator import itemgetter
ig0137 = itemgetter(0, 1, 3, 7)
newlist = ig0137(oldlist)

The itemgetter is more efficient than a list comprehension if you are using it in a loop

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • I like how this answers the actual question about efficiency, rather than simply providing alternative methods to call. – mrisher Feb 01 '14 at 02:44
6

For the first there's also this alternative:

a, b = s.partition('-')[::2]

For the latter, since there's no clear interval there is no way to do it too clean. But this might suit your needs:

newlist = [oldlist[k] for k in (0, 1, 3, 7)]
Wolph
  • 78,177
  • 11
  • 137
  • 148
  • Please refer to [this](http://stackoverflow.com/questions/509211/good-primer-for-python-slice-notation) to understand the list slicing. – John Wang Aug 29 '12 at 07:27
  • @user1544915: the first works by slicing the list with an interval of 2, so if you have a list like this: `[0, 1, 2, 3, 4, 5]` it will return: `[0, 2, 4]`. If you try `[::3]` it would return `[0, 3]` – Wolph Aug 29 '12 at 16:15
4

You can use Python's extended slicing feature to access a list periodically:

>>> a = range(10)
>>> # Pick every other element in a starting from a[1]
>>> b = a[1::2]
>>> print b
>>> [1, 3, 5, 7, 9]

Negative indexing works as you'd expect:

>>> c = a[-1::-2]
>>> print c
>>> [9, 7, 5, 3, 1]

For your case,

>>> a, b = s.partition('-')[::2]
edsv
  • 62
  • 4
2

the common practice in Python to pick 1st and 3rd values is:

a, _, b = s.partition('-')

And to pick specified elements in a list you can do :

newlist = [oldlist[k] for k in (0, 1, 3, 7)]
John Wang
  • 4,562
  • 9
  • 37
  • 54
1

If you don't need to retain the middle field you can use split (and similarly rsplit) with the optional maxsplit parameter to limit the splits to the first (or last) match of the separator:

a, b = s.split('-', 1)

This avoids a throwaway temporary or additional slicing.

The only caveat is that with split, unlike partition, the original string is returned if the separator is not found. The attempt to unpack will fail as a result. The partition method always returns a 3-tuple.

Kevin Thibedeau
  • 3,299
  • 15
  • 26