【发布时间】:2012-03-04 22:58:12
【问题描述】:
我想知道是否有一个很好的 Pythonic 方法来分解这个列表:
['1,2,3', '22', '33']
进入列表:
['1','2','3','22','33']
使用列表推导?
【问题讨论】:
标签: python list list-comprehension
我想知道是否有一个很好的 Pythonic 方法来分解这个列表:
['1,2,3', '22', '33']
进入列表:
['1','2','3','22','33']
使用列表推导?
【问题讨论】:
标签: python list list-comprehension
使用列表推导,它看起来像这样:
>>> L = ['1,2,3', '22', '33']
>>> [x for s in L for x in s.split(",")]
['1', '2', '3', '22', '33']
【讨论】:
我不会使用sum,因为它会重复连接并创建大量副本。我会这样做:
>>> import itertools
>>> l = ['1,2,3', '22', '33']
>>> list(itertools.chain.from_iterable(s.split(',') for s in l))
['1', '2', '3', '22', '33']
确实,对于非常短的列表,它会稍微慢一些:
>>> %timeit sum((s.split(',') for s in l), [])
100000 loops, best of 3: 2.38 us per loop
>>> %timeit list(itertools.chain.from_iterable(s.split(',') for s in l))
100000 loops, best of 3: 3.51 us per loop
但是对于长列表,它方式比使用sum快:
>>> l = ['1,2,3', '22', '33'] * 500
>>> %timeit sum((s.split(',') for s in l), [])
100 loops, best of 3: 6.22 ms per loop
>>> %timeit list(itertools.chain.from_iterable(s.split(',') for s in l))
1000 loops, best of 3: 664 us per loop
不过,其实我更喜欢wim 的回答。快速测试表明它是所有情况下启动速度最快的:
>>> l = ['1,2,3', '22', '33']
>>> %timeit [x for s in l for x in s.split()]
1000000 loops, best of 3: 1.45 us per loop
>>> l = ['1,2,3', '22', '33'] * 500
>>> %timeit [x for s in l for x in s.split()]
1000 loops, best of 3: 559 us per loop
【讨论】:
chain.from_iterable 解决方案的最大优势不是速度,而是在我看来它比 sum 更直接..
由于已经使用 sum() 函数作为解决方案发布了两个答案,我想我会提供另一种方式,使用 itertools.chain
from itertools import chain
x = ['1,2,3', '22', '33']
result = chain.from_iterable(i.split(',') for i in x)
print result
#<itertools.chain object at 0x1004b5e10>
chain 命令的结果是一个生成器。因此,您可以循环遍历结果,或将其转换为另一种序列类型(元组、列表、集合......)
【讨论】:
chain.from_iterable() 代替chain(*...)。更明确的东西......
* 运算符将生成器转换为元组,从而破坏了使用元组的意义。
分解你的问题。你永远看不到如何一次解决整个问题,而且 Python 从来没有简单的内置解决方案来解决整个问题。弄清楚你的问题中最基本的部分是什么,并且每个部分通常都有简单的直接解决方案。然后结合解决方案。另外,不要指望你可以在问题上挥动一个神奇的口号,比如“列表理解”,让它消失。弄清楚您的解决方案需要做什么,然后考虑列表推导式是否可以做到这一点。
你有一个字符串'1,2,3'。您需要将其拆分为多个字符串的列表,其中包含由逗号分隔的原始字符串位:
>>> help(str.split)
Help on method_descriptor:
split(...)
S.split([sep [,maxsplit]]) -> list of strings
Return a list of the words in the string S, using sep as the
delimiter string. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are removed
from the result.
>>> '1,2,3'.split(',')
['1', '2', '3']
>>> '3'.split(',')
['3']
现在,您有一个字符串列表,并且您希望将每个字符串拆分为一个列表,如上:
>>> [s.split(',') for s in ['1','2','3','22','33']]
[['1'], ['2'], ['3'], ['22'], ['33']]
现在您已经有了一个列表列表。您需要一个包含列表列表中每个列表元素的列表。操作“给我列表列表中的每个列表中的每一件事”非常自然地映射到列表推导,如下所示:
>>> list_of_lists = [[1, 2, 3], ['a', 'b', 'c']]
>>> [thing for alist in list_of_lists for thing in alist]
[1, 2, 3, 'a', 'b', 'c']
把它们放在一起:
>>> [bit for string in ['1','2','3','22','33'] for bit in string.split(',')]
['1', '2', '3', '22', '33']
这就是您使用列表推导解决此问题的方法。其他答案中还有许多其他潜在的解决方案,这些解决方案在技术方面更好。但是,如果您是 Python 新手,学习整个标准库(尤其是功能强大但抽象的东西,例如 itertools)会很困难,而且您不必觉得必须这样做。从长远来看,熟悉基础知识将为您提供更多帮助。
【讨论】:
这是我能想到的最简单的解决方案。
它将sum() 与生成器表达式一起使用,因为您实际上并不需要创建子列表。
>>> a = ['1,2,3', '22', '33']
>>> sum((s.split(',') for s in a), [])
['1', '2', '3', '22', '33']
【讨论】:
一个简单的方法是:
>>> lst = ['1,2,3', '22', '33']
>>> res = []
>>> for x in lst:
... res.extend(x.split(','))
>>> res
['1', '2', '3', '22', '33']
虽然它不使用列表推导,但我不明白为什么你会在这种情况下使用它。
【讨论】:
你可以这样做(假设你的列表叫做 l):
sum([s.split(',') for s in l], [])
【讨论】: