do you master list comprehensions?

Nick Coghlan ncoghlan at iinet.net.au
Wed Dec 15 07:21:53 EST 2004


Will Stuyvesant wrote:
> Here is a question about list comprehensions [lc].  The
> question is dumb because I can do without [lc]; but I am
> posing the question because I am curious.
> 
> This:
> 
> 
>>>>data = [['foo','bar','baz'],['my','your'],['holy','grail']]
>>>>result = []
>>>>for d in data:
> 
> ...     for w in d:
> ...        result.append(w)
> 
>>>>print result
> 
> ['foo', 'bar', 'baz', 'my', 'your', 'holy', 'grail']
> 
> puts all the words in a list, like I want.

There's a way to avoid generating the intermediate list if you don't actually 
need it (e.g. you want to feed the sequence to another method):

.>>> data = [['foo','bar','baz'],['my','your'],['holy','grail']]
.>>> from itertools import chain
.>>> result = "".join(chain(*data))
'foobarbazmyyourholygrail'


Some timing with integers:

C:\>python -m timeit -s "data = [range(x) for x in range(1000)]" "L= []; map(L.e
xtend, data); max(L)"
10 loops, best of 3: 78.5 msec per loop

C:\>python -m timeit -s "data = [range(x) for x in range(1000)]; from Tkinter im
port _flatten" "max(_flatten(data))"
10 loops, best of 3: 58.4 msec per loop

C:\>python -m timeit -s "data = [range(x) for x in range(1000)]; from itertools
import chain" "max(chain(*data))"
10 loops, best of 3: 43 msec per loop

And with strings:

C:\>python -m timeit -s "data = [map(str, range(x)) for x in range(1000)]" "L= [
]; map(L.extend, data); ''.join(L)"
10 loops, best of 3: 106 msec per loop

C:\>python -m timeit -s "data = [map(str, range(x)) for x in range(1000)]; from
Tkinter import _flatten" "''.join(_flatten(data))"
10 loops, best of 3: 85.4 msec per loop

C:\>python -m timeit -s "data = [map(str, range(x)) for x in range(1000)]; from
itertools import chain" "''.join(chain(*data))"
10 loops, best of 3: 1.2 sec per loop ****** OUCH!!

C:\>python -m timeit -s "data = [map(str, range(x)) for x in range(1000)]; from
itertools import chain" "''.join(list(chain(*data)))"
10 loops, best of 3: 107 msec per loop


Yikes - looks like chain() really sucks for str.join. However, the addition of 
the 'list' call makes a big difference. Maybe PySequence_Fast should be called 
PySequence_SlowAsADeadDingo() in this case ;)

(FYI, I filed bug report #1085744 on SF about this)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.skystorm.net



More information about the Python-list mailing list