如何使用列表推导式来处理嵌套列表?

问题描述 投票:0回答:13

我有这个嵌套列表:

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']]

我想将

l
中的每个元素转换为
float
。我有这个代码:

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

如何使用嵌套列表理解来解决问题?


另请参阅:如何从列表理解而不是嵌套列表中获得平坦结果?

python list nested list-comprehension
13个回答
475
投票

以下是如何使用嵌套列表理解来做到这一点:

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

这将为您提供一个列表列表,与您开始时类似,只是使用浮点数而不是字符串。

如果您想要一个平面列表,那么您可以使用

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

注意循环顺序 -

for x in l
在这个循环中排在第一位。


383
投票

以下是将嵌套 for 循环转换为嵌套列表理解的方法:

以下是嵌套列表理解的工作原理:

            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]

对于您的情况,如果您想要一个平面列表,它将是这样的。

In [4]: new_list = [float(y) for x in l for y in x]

63
投票

不确定您想要的输出是什么,但如果您使用列表理解,则顺序遵循嵌套循环的顺序,而嵌套循环的顺序是相反的。所以我得到了我认为你想要的东西:

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

原则是:使用与嵌套 for 循环相同的顺序。


55
投票
>>> 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]

11
投票

我想分享列表理解的实际工作原理,特别是对于嵌套列表理解:

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

实际上与:

相同
new_list=[]
for x in l:
    new_list.append(float(x))

现在进行嵌套列表理解:

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

等同于:

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)

输出:

[[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]]

9
投票

我有一个类似的问题需要解决,所以我遇到了这个问题。我对安德鲁·克拉克和纳拉扬的答案进行了性能比较,我想分享一下。

两个答案之间的主要区别在于它们如何迭代内部列表。其中之一使用内置的 map,而另一种则使用列表理解。如果不需要使用 lambdas,Map 函数比其等效的列表理解具有轻微的性能优势。因此,在这个问题的上下文中,map

应该比列表理解表现得稍好一些。 

让我们做一个性能基准测试来看看它是否真的如此。我使用 python 版本 3.5.0 来执行所有这些测试。在第一组测试中,我希望将每个列表的元素保持为

10,并且列表的数量从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

在下一组测试中,我想将每个列表的元素数量增加到

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

让我们勇敢地迈出一步,将列表中的元素数量修改为

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

从这些测试中我们可以得出结论,在这种情况下,

map

比列表理解具有性能优势。如果您尝试投射到 
int
str
,这也适用。对于每个列表中元素较少的少量列表,差异可以忽略不计。对于每个列表包含更多元素的较大列表,人们可能喜欢使用 
map
 而不是列表理解,但这完全取决于应用程序需求。

但是我个人认为列表理解比

map

 更具可读性和惯用性。它是Python事实上的标准。通常人们(特别是初学者)使用列表理解比
map
更熟练和舒适。


3
投票
如果您不喜欢嵌套列表推导式,您也可以使用

map 函数,

>>> 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]]
    

3
投票
这个问题不需要使用for循环就可以解决。单行代码就足够了。将嵌套映射与 lambda 函数一起使用也可以在这里工作。

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)

输出列表如下:

[[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]]
    

2
投票
是的,你可以用这样的代码来做到:

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

2
投票
如果需要扁平列表:

[y for x in l for y in x]
如果需要嵌套列表(列表中的列表):

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

0
投票
我认为最好的方法是使用 python 的

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]
    

0
投票
deck = [] for rank in ranks: for suit in suits: deck.append(('%s%s')%(rank, suit))

这可以使用列表理解来实现:

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

0
投票
是的,您可以执行以下操作。

[[float(y) for y in x] for x in l]
    
© www.soinside.com 2019 - 2024. All rights reserved.