views:

169

answers:

3

Hello, I'm trying to obtain the n-th elements from a list of tuples. I have something like

elements = [(1,1,1),(2,3,7),(3,5,10)]

and I want to extract only the second elements of each tuple into an array:

seconds = [1, 3, 5]

I know that it could be done with a for but I wanted to know if there's another way since I have thousands of tuples.
any ideas? Thank you =)

+19  A: 
[x[1] for x in elements]
luc
+1 for typing faster than me
derekerdmann
It is not because I was fatser but because I've developped a SO auto-reply which is able to find the list comprehension for converting one list into an other. ;-)
luc
+12  A: 

I know that it could be done with a FOR but I wanted to know if there's another way

There is another way. You can also do it with map and itemgetter:

>>> from operator import itemgetter
>>> map(itemgetter(1), elements)

This still performs a loop internally though and it is slightly slower than the list comprehension:

setup = 'elements = [(1,1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))

Results:

Method 1: 1.25699996948
Method 2: 1.46600008011

If you need to iterate over a list then using a for is fine.

Mark Byers
thxs a lot, i'll do that
pleasedontbelong
+5  A: 

This also works:

zip(*elements)[1]

(I am mainly posting this, to prove to myself that I have groked zip...)

See it in action:

>>> help(zip)

Help on built-in function zip in module builtin:

zip(...)

zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]

Return a list of tuples, where each tuple contains the i-th element from each of the argument sequences. The returned list is truncated in length to the length of the shortest argument sequence.

>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> zip(*elements)
[(1, 2, 3), (1, 3, 5), (1, 7, 10)]
>>> zip(*elements)[1]
(1, 3, 5)
>>>

Neat thing I learned today: Use *list in arguments to create a parameter list for a function...

Daren Thomas
and use `**dict` to create keyword arguments: `def test(foo=3, bar=3): return foo*bar` then `d = {'bar': 9, 'foo'=12}; print test(**d)`
Wayne Werner
@Wayne Werner: Yep. This stuff was all just passive knowledge (I don't often use it) - but it's good to be reminded now and then so you know where / what to look for...
Daren Thomas
True story - I find that in anything I use often enough (Python, vim), I tend to need reminders of neat/cool features that I've forgotten because I don't use them *that* often.
Wayne Werner