List comprehension on a nested list?

Multi tool use
Multi tool use


List comprehension on a nested list?



I have this nested list:


l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]



Now, what I want to do is convert each element in a list to float. My solution is this:


newList =
for x in l:
for y in x:
newList.append(float(y))



But can this be done using nested list comprehension, right?



what I've done is:


[float(y) for y in x for x in l]



But then the result is bunch of 100's with the sum of 2400.



any solution, an explanation would be much appreciated. Thanks!





Do you also want to flatten your list?
– Greg Hewgill
Aug 6 '13 at 6:05





@GregHewgill: OP didn't reply, but based on the answer they accepted, seems they wanted to keep the nesting as is.
– smci
Feb 2 at 20:39





11 Answers
11



Here is how you would do this with a nested list comprehension:


[[float(y) for y in x] for x in l]



This would give you a list of lists, similar to what you started with except with floats instead of strings. If you want one flat list then you would use [float(y) for x in l for y in x].


[float(y) for x in l for y in x]


>>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> new_list = [float(x) for xs in l for x in xs]
>>> new_list
[40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]



Here is how nested list comprehension works:
enter image description here


l a b c d e f
↓ ↓ ↓ ↓ ↓ ↓ ↓
In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ]
In [2]: for a in l:
...: for b in a:
...: for c in b:
...: for d in c:
...: for e in d:
...: for f in e:
...: print(float(f))
...:
1.0

In [3]: [float(f)
for a in l
...: for b in a
...: for c in b
...: for d in c
...: for e in d
...: for f in e]
Out[3]: [1.0]

#Which can be written in single line as
In [4]: [float(f) for a in l for b in a for c in b for d in c for e in d for f in e]
Out[4]: [1.0]





Super useful! Makes it clear that loops (top-to-bottom) are ordered left to right in the generator. This not obvious since in (f(x) for x in l) places the second line of the for-loop equivalent on the left.
– user48956
Jan 11 at 18:11


(f(x) for x in l)





Great useful illustration of the (slightly non-obvious at first glance) syntax of nested comprehensions.
– wom
Mar 7 at 19:36



Not sure what your desired output is, but if you're using list comprehension, the order follows the order of nested loops, which you have backwards. So I got the what I think you want with:


[float(y) for x in l for y in x]



The principle is: use the same order you'd use in writing it out as nested for loops.





this should be the answer, as some times we don't want to square bracket the iteratool
– zinking
Apr 19 '17 at 1:48





this may not be the correct answer as it outputs a non nested list, but it is what I was looking for, specially the principle. Thanks!
– Rodrigo E. Principe
Sep 29 '17 at 10:52



Since i am little late here but i wanted to share how actually list comprehension works especially nested list comprehension :


New_list= [[float(y) for x in l]



is actually same as :


New_list=
for x in l:
New_list.append(x)



And now nested list comprehension :


[[float(y) for y in x] for x in l]



is same as ;


new_list=
for x in l:
sub_list=
for y in x:
sub_list.append(float(y))

new_list.append(sub_list)

print(new_list)



output:


[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]



If you don't like nested list comprehensions, you can make use of the map function as well,


>>> from pprint import pprint

>>> l = l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

>>> pprint(l)
[['40', '20', '10', '30'],
['20', '20', '20', '20', '20', '30', '20'],
['30', '20', '30', '50', '10', '30', '20', '20', '20'],
['100', '100'],
['100', '100', '100', '100', '100'],
['100', '100', '100', '100']]

>>> float_l = [map(float, nested_list) for nested_list in l]

>>> pprint(float_l)
[[40.0, 20.0, 10.0, 30.0],
[20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0],
[30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0],
[100.0, 100.0],
[100.0, 100.0, 100.0, 100.0, 100.0],
[100.0, 100.0, 100.0, 100.0]]





Your code generates map objects instead of lists: >>> float_l = [map(float, nested_list) for nested_list in l] [[<map at 0x47be9b0>], [<map at 0x47be2e8>], [<map at 0x47be4a8>], [<map at 0x47beeb8>], [<map at 0x484b048>], [<map at 0x484b0b8>]] but adding an additional call to list it works as expected: >>> float_l = [list(map(float, nested_list)) for nested_list in l]
– pixelperfect
Mar 17 '17 at 15:49



>>> float_l = [map(float, nested_list) for nested_list in l]


[[<map at 0x47be9b0>], [<map at 0x47be2e8>], [<map at 0x47be4a8>], [<map at 0x47beeb8>], [<map at 0x484b048>], [<map at 0x484b0b8>]]


>>> float_l = [list(map(float, nested_list)) for nested_list in l]





@pixelperfect that is due to the (misinformed ..) change in python3 to return generators out of comprehensions.
– javadba
Mar 4 at 4:56



python3



I had a similar problem to solve so I came across this question. I did a performance comparison of Andrew Clark's and narayan's answer which I would like to share.



The primary difference between two answers is how they iterate over inner lists. One of them uses builtin map, while other is using list comprehension. Map function has slight performance advantage to its equivalent list comprehension if it doesn't require the use lambdas. So in context of this question map should perform slightly better than list comprehension.


map



Lets do a performance benchmark to see if it is actually true. I used python version 3.5.0 to perform all these tests. In first set of tests I would like to keep elements per list to be 10 and vary number of lists from 10-100,000


>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10]"
>>> 10000 loops, best of 3: 19.6 usec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100]"
>>> 10000 loops, best of 3: 19.6 usec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*1000]"
>>> 1000 loops, best of 3: 1.43 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*1000]"
>>> 100 loops, best of 3: 1.91 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10000]"
>>> 100 loops, best of 3: 13.6 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10000]"
>>> 10 loops, best of 3: 19.1 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 164 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 216 msec per loop



enter image description here



In the next set of tests I would like to raise number of elements per lists to 100.


>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 110 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 151 usec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.11 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.5 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 11.2 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 16.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 134 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 171 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.32 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.7 sec per loop



enter image description here



Lets take a brave step and modify the number of elements in lists to be 1000


>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 800 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 1.16 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 8.26 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 11.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 83.8 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 118 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 868 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 1.23 sec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 9.2 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 12.7 sec per loop



enter image description here



From these test we can conclude that map has a performance benefit over list comprehension in this case. This is also applicable if you are trying to cast to either int or str. For small number of lists with less elements per list, the difference is negligible. For larger lists with more elements per list one might like to use map instead of list comprehension, but it totally depends on application needs.


map


int


str


map



However I personally find list comprehension to be more readable and idiomatic than map. It is a de-facto standard in python. Usually people are more proficient and comfortable(specially beginner) in using list comprehension than map.


map


map



Yes, you can do it with such a code:


l = [[float(y) for y in x] for x in l]





[float(y) for y in x for x in l] this would result to a bunch of 100's with a sum of 2400.
– Boy Pasmo
Aug 6 '13 at 6:09


[float(y) for y in x for x in l]



This Problem can be solved without using for loop.Single line code will be sufficient for this. Using Nested Map with lambda function will also works here.


l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

map(lambda x:map(lambda y:float(y),x),l)



And Output List would be as follows:


[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]





Do lambdas has any performance benefits over say @Andrew Clark or Harry Binswanger's solutions (the more vanilla list comprehension)? As lambdas seem harder to read.
– Splatmistro
Oct 2 '17 at 13:45



The best way to do this in my opinion is to use python's itertools package.


itertools


>>>import itertools
>>>l1 = [1,2,3]
>>>l2 = [10,20,30]
>>>[l*2 for l in itertools.chain(*[l1,l2])]
[2, 4, 6, 20, 40, 60]


deck =
for rank in ranks:
for suit in suits:
deck.append(('%s%s')%(rank, suit))



This can be achieved using list comprehension:


[deck.append((rank,suit)) for suit in suits for rank in ranks ]





This does not appear to address the question on top at all. Please note that everything posted as an answer must be an attempt to answer the question it is posted to.
– Baum mit Augen
Mar 22 at 11:46





While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations!
– Filnor
Mar 22 at 11:46





Nested for loop using list comprehension,
– ADITYA KUMAR
Mar 22 at 11:56






Ok, so apparently, this is an attempt to answer the question. However, this appears to be about an entirely different scenario than in OP, you don't even deal with nested lists as input, and even if you change that your suggestion is pretty much what OP already tried. Also, I don't see how an example about cards helps when the question is about converting strings to float.
– Baum mit Augen
Mar 22 at 12:02






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

OOFc8Ui11dUlnK,nhY3 z8,hm0mV1N9M4i a Xr8odB1Le9,NcNZT17xXSE wQLUgGZf,gN2hk
psMsKk4 OhTiUx76eKCopaVw 1nfAEAN C ezUBnQg,QKmBkFoozPkxqucx,Q Cq8c5C6DkMGe4hHkonFxwupctFV

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications