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

How can I use list comprehensions to process a nested list?

提问人:Boy Pasmo 提问时间:8/6/2013 最后编辑:Karl KnechtelBoy Pasmo 更新时间:1/27/2023 访问量:241365

问:

我有这个嵌套列表:

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

我想将每个元素转换为 .我有这个代码:lfloat

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

如何用嵌套列表推导来解决这个问题?


Смотритетакже: 如何从列表推导式而不是嵌套列表中获得平面结果?

python 嵌套 列表推导

评论

22赞 Greg Hewgill 8/6/2013
想把你的清单扁平化吗?
3赞 smci 2/3/2018
@GregHewgill:OP没有回复,但根据他们接受的答案,他们似乎想保持嵌套的原样。
0赞 Karl Knechtel 2/19/2022
参见:treyhunner.com/2015/12/python-list-comprehensions-now-in-color
0赞 Karl Knechtel 8/3/2022
[float(y) for y in x for x in l] 本身不起作用。它之所以有效,只是因为以前代码中遗留的现有定义。x

答:

55赞 falsetru 8/6/2013 #1
>>> 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]
472赞 Andrew Clark 8/6/2013 #2

以下是使用嵌套列表推导式执行此操作的方法:

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

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

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

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

请注意循环顺序 - 在此顺序中排在第一位。for x in l

2赞 Victor 8/6/2013 #3

是的,您可以使用这样的代码来完成:

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

评论

0赞 Boy Pasmo 8/6/2013
[float(y) for y in x for x in l]这将导致一堆 100 的总和为 2400。
3赞 narayan 11/27/2015 #4

如果你不喜欢嵌套列表推导式,你也可以使用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]]

评论

0赞 pixelperfect 3/17/2017
您的代码生成的是 map 对象而不是列表:但添加一个额外的调用来列出它,它按预期工作:>>> 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]
0赞 WestCoastProjects 3/4/2018
@pixelperfect这是由于(被误导的...)更改以返回理解之外的生成器。python3
0赞 Thomasillo 7/12/2016 #5

在我看来,最好的方法是使用 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]
62赞 Harry Binswanger 3/26/2017 #6

不确定您想要的输出是什么,但如果您使用的是列表推导式,则顺序遵循嵌套循环的顺序,这是向后的。所以我得到了我认为你想要的:

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

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

评论

0赞 zinking 4/19/2017
这应该是答案,因为有时我们不想将 Iteratool 放在方括号中
3赞 Rodrigo E. Principe 9/29/2017
这可能不是正确的答案,因为它输出了一个非嵌套列表,但这就是我一直在寻找的,特别是原理。谢谢!
2赞 WestCoastProjects 3/5/2021
这是不正确的:周围应该有括号[float(y)]
3赞 Aakash Goel 4/27/2017 #7

这个问题可以在不使用 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]]

评论

1赞 Stefan Collier 10/2/2017
lambda 是否比 @Andrew Clark 或 Harry Binswanger 的解决方案(更普通的列表理解)有任何性能优势?因为 lambda 似乎更难阅读。
1赞 WestCoastProjects 3/5/2021
在几乎任何其他通用编程语言中,我们都会使用链式编程 - 按照您显示的内容。但是看看它在 python 中有多丑陋 - 特别是考虑到上面的输出是不够的:它是一个生成器而不是一个列表。需要添加更多的样板来完成图片。尝试和类似的库在某种程度上摆脱这个陷阱。maplist(list( .. ) )fluentpy
376赞 Rahul 7/13/2017 #8

以下是将嵌套 for 循环转换为嵌套列表推导式的方法:

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]

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

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

评论

39赞 user48956 1/12/2018
超级有用!明确循环(从上到下)在生成器中从左到右排序。这并不明显,因为 in places 中 for 循环的第二行等效项在左侧。(f(x) for x in l)
0赞 dtc 4/15/2021
@user48956 是的,我认为将嵌套列表理解作为单行并不是很直观。这种用法将是一种反模式的 IMO
11赞 Aaditya Ura 10/7/2017 #9

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

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赞 Sohaib Farooqi 1/18/2018 #10

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

两个答案之间的主要区别在于它们如何遍历内部列表。其中一个使用内置地图,而另一个使用列表推导。如果 Map 函数不需要使用 lambdas,则与其等效列表推导相比,它具有轻微的性能优势。因此,在这个问题的上下文中,应该比列表理解稍微好一些。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

enter image description here

在下一组测试中,我想将每个列表的元素数增加到 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

让我们勇敢地迈出一步,将列表中的元素数修改为 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

从这些测试中,我们可以得出结论,在这种情况下,与列表理解相比,它具有性能优势。如果您尝试强制转换为 或 ,这也适用。对于每个列表元素较少的少量列表,差异可以忽略不计。对于每个列表包含更多元素的较大列表,可能希望使用列表推导而不是列表推导,但这完全取决于应用程序需求。mapintstrmap

但是,我个人认为列表理解比 更具可读性和惯用性。它是 python 中的事实标准。通常人们在使用列表理解方面比 .mapmap

0赞 ADITYA KUMAR 3/22/2018 #11
    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 ]

评论

1赞 Baum mit Augen 3/22/2018
这似乎根本没有解决上面的问题。请注意,作为答案发布的所有内容都必须是试图回答它所发布的问题。
0赞 Filnor 3/22/2018
虽然此代码片段可能会解决问题,但包含解释确实有助于提高帖子的质量。请记住,您将来正在为读者回答问题,而这些人可能不知道您提出代码建议的原因。也请尽量不要用解释性注释来填充你的代码,这会降低代码和解释的可读性!
0赞 ADITYA KUMAR 3/22/2018
使用列表推导的嵌套 for 循环,
1赞 Baum mit Augen 3/22/2018
好吧,很明显,这是试图回答这个问题。然而,这似乎是一个与 OP 完全不同的场景,你甚至不处理嵌套列表作为输入,即使你改变了它,你的建议也几乎是 OP 已经尝试过的。另外,当问题是关于将字符串转换为浮点数时,我不明白关于卡片的示例有什么帮助。
0赞 BeerHuntor 10/13/2021
忽略上面...您的评论帮助我解决了这个问题。谢谢
0赞 user1142317 9/7/2018 #12

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

[[float(y) for y in x] for x in l]
2赞 learner 12/29/2021 #13

如果需要扁平化列表:

[y for x in l for y in x]

如果需要嵌套列表(列表中的列表):

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