对嵌套迭代对象的理解?

我有这样一个嵌套列表:

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

如何用嵌套的列表理解来解决这个问题?


另见:我怎么能从一个列表理解而不是一个嵌套列表得到一个扁平的结果?< / >

221819 次浏览
>>> 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]

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

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

这将给你一个列表的列表,类似于你开始的,只是用浮点数而不是字符串。如果你想要一个平面列表,那么你可以使用[float(y) for x in l for y in x]

是的,你可以用这样的代码:

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

如果你不喜欢嵌套的列表推导式,你也可以使用<强> < /地图强大>函数,

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

在我看来,最好的方法是使用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]

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

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

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

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

下面是如何将嵌套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]

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

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

我有一个类似的问题要解决,所以我遇到了这个问题。我对Andrew Clark和narayan的答案做了一个性能比较,我想和大家分享一下。

两个答案之间的主要区别是它们如何遍历内部列表。其中一个使用内置的地图,而另一个使用列表理解。如果Map函数不需要使用lambdas,则它的等效列表理解具有轻微的性能优势。所以在这个问题的上下文中,map的表现应该比列表理解略好。

让我们做一个性能基准测试,看看它是否真实。我使用python 3.5.0版本来执行所有这些测试。在第一组测试中,我想保持每个列表的元素为10,并从10 - 100000改变列表的数量

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

在下一组测试中,我想将每个列表的元素数量提高到One hundred.

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

从这些测试中,我们可以得出结论,在这种情况下,map的性能优于列表理解。如果你试图强制转换到intstr,这也适用。对于数量较少且每个列表的元素较少的列表,这种差异可以忽略不计。对于每个列表中有更多元素的更大的列表,可能会使用map而不是列表推导式,但这完全取决于应用程序的需要。

然而,我个人认为列表理解比map更具可读性和惯用性。它是python中事实上的标准。通常人们在使用列表理解方面比map更熟练和舒适(尤其是初学者)。

    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 ]

是的,你可以这样做。

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

如果需要一个扁平的列表:

[y for x in l for y in x]

如果需要一个嵌套列表(list In list):

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