Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it possible to convert this loop into a list comprehension in python

I have this small bit of code which I want to know if it could be written in list comprehension. The while loop part is what I am interested in condensing.

>>> sum=33
>>> final_list=[]
>>> LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 
           1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1]
>>> while sum>0:
...    final_list.append(LastCoin[sum])
...    sum-=LastCoin[sum]
... 
>>> print final_list
[1, 2, 5, 5, 5, 5, 5, 5]
>>> 
like image 928
eagertoLearn Avatar asked Feb 14 '23 00:02

eagertoLearn


1 Answers

Is there any good reason you are trying to use a list comprehension?

I see personally a lot of people trying to wedge list comprehensions where they don't belong, because, you know, 'list comprehensions are faster - they're in native C! whereas your boring loop is in interpreted Python'. That's not always true.

Just as a reference, if we compare your original solution, which is concise and readable, against the two proposed answers, you may find your assumptions violated:

In [5]: %%timeit
   ...: sum=33
   ...: while sum > 0:
   ...:     final_list.append(LastCoin[sum])
   ...:     sum -= LastCoin[sum]
   ...:
100000 loops, best of 3: 1.96 µs per loop

In [6]: %%timeit
   ...: sum=33
   ...: susu = [sum]
   ...: susu.extend(x for x in xrange(sum,-1,-1)
   ...:             if x==(susu[-1]-LastCoin[susu[-1]])!=0)
   ...: fifi = [LastCoin[x] for x in susu]
   ...:
100000 loops, best of 3: 10.4 µs per loop
# 5x slower

In [10]: %timeit final_list = [LastCoin[reduce(lambda x, y: x - LastCoin[x], range(counter, i, -1))] for i in range(counter -1, 0, -1) if reduce(lambda x, y: x - LastCoin[x], range(counter, i, -1))]
10000 loops, best of 3: 128 µs per loop
# More than 60x slower!!

A list comprehension is a good choice if you are trying to do something for every element in a list - filtering (test every element for true/false), translation, etc. where the operation is separate for every element (and, theoretically, could often be parallelized). It's not very good at loops which do processing and change state during the loop, and they usually look ugly when you try. In this particular case, you only look at 8 items as you go through the list, because you are manually calculating indices to look at. In the list comprehension case, you would have to at least look at all 33.

I don't know if that's your motivation, but if it is, just leave it as a loop. Python loops aren't that bad after all!

like image 96
Corley Brigman Avatar answered Mar 22 '23 22:03

Corley Brigman