List comprehension on a nested list?

后端 未结 12 913
情话喂你
情话喂你 2020-11-22 07:57

I have this nested list:

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


        
12条回答
  •  一向
    一向 (楼主)
    2020-11-22 08:22

    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.

    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
    

    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
    

    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
    

    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.

    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.

提交回复
热议问题