2013-08-06 141 views
132

我有这样的嵌套列表:在嵌套列表上理解列表?

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

现在,我想要做的是每个元素转换列表中的浮动。我的解决方案是这样的:

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

但这可以使用嵌套列表理解,对吗?

什么,我所做的就是:

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

但随后的结果是与2400的

任何解决方案和一束100的的,的解释将不胜感激。谢谢!

+12

你是否也想要展平你的名单? –

+0

@GregHewgill:OP没有回复,但根据他们接受的答案,似乎他们想保持嵌套。 – smci

回答

195

这里是你将如何使用嵌套列表理解这样做:

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

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

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

是的,你可以用这样的代码做到这一点:

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

'[float(y)for y in x for x in l]'这将导致一堆100个数的总和为2400. –

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

您的代码生成地图对象而不是列表: >>> >>> float_l = [ nested_list的地图(float,nested_list)[] [ ] [[], [], [], [], , [<在0x484b048地图>] [<地图在0x484b0b8>]] ' 但是添加附加的呼叫到列表它按预期工作: '>>> FLOAT_L = [表(图(浮筒,nested_list ))for nested_list in l]' – pixelperfect

+0

@pixelperfect这是由于(* misinformed * ..)在'python3'中改变,使得生成器不能被理解。 – javadba

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

不知道你想要的输出是什么,但如果你使用列表中理解,顺序如下嵌套循环,你有向后的顺序。所以,我得到了你想要我认为:

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

其原理是:利用你在写出来嵌套的for循环使用相同的顺序。

+0

这应该是答案,因为有些时候我们不希望将括号括起来iteratool – zinking

+0

这可能不是正确的答案,因为它输出一个非嵌套列表,但这正是我正在寻找的,特别是*原则* 。谢谢! –

1

这个问题可以在不使用循环的情况下解决。单线代码就足够了。使用带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]0]

+1

与安德鲁·克拉克或哈里·宾斯旺格的解决方案(更多香草列表理解)相比,lambda表达式有什么优势?由于lambda似乎难以阅读。 – Splatmistro

18
  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] 
+0

超好用!清楚地说明循环(从上到下)从发生器左侧到右侧排列。这在'(f(x)for x in l)'中不明显,因为它将循环等效的第二行放在左边。 – user48956

+0

嵌套理解的(非常明显的乍一看)语法的很有用的例子。 – wom

4

既然我有点晚了这里,但我想分享列表理解如何实际工作尤其是嵌套列表理解:

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

实际上是一样的:

New_list=[] 
for x in l: 
    New_list.append(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]] 
2

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

两个答案的主要区别在于它们如何遍历内部列表。其中一个使用内建的map,而其他使用列表理解。 Map function has slight performance advantage to its equivalent list comprehension if it doesn't require the use lambdas。所以在这个问题的背景下,map应该比列表理解执行略好。

让我们做一个性能基准来判断它是否真的如此。我使用python 3.5.0版来执行所有这些测试。在第一组测试,我想保持每列表元素是和改变列表的数量从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

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

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

让作为勇敢步骤和修改列表元素的数量是

>>> 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更熟练和舒适(特别是初学者)。