家伙。 我试图找到最优雅的解决一个问题,不知道是否Python有任何内置的什么,我试图做的。
我在做什么的就是这个。 我有一个列表, A
和我有一个函数f
这需要一个项目,并返回一个列表。 我可以用一个列表理解的一切转换成A
像这样;
[f(a) for a in A]
但是,这回列表的列表;
[a1,a2,a3] => [[b11,b12],[b21,b22],[b31,b32]]
我真正想要的是让扁平的列表;
[b11,b12,b21,b22,b31,b32]
现在,其他语言有它; 它传统上被称为flatmap
在函数式编程语言和.Net调用它SelectMany
。 巨蟒是否有类似的东西吗? 是否有一个整洁的方式映射在列表的功能,扁平化的结果呢?
我试图解决的实际问题是这样的; 开始的目录列表,找到所有的子目录。 所以;
import os
dirs = ["c:\\usr", "c:\\temp"]
subs = [os.listdir(d) for d in dirs]
print subs
currentliy给了我一个列表的清单,但我真的希望有一个列表。
Answer 1:
你可以在一个单一的列表理解嵌套迭代:
[filename for path in dirs for filename in os.listdir(path)]
Answer 2:
>>> listOfLists = [[1, 2],[3, 4, 5], [6]]
>>> reduce(list.__add__, listOfLists)
[1, 2, 3, 4, 5, 6]
我猜迭代工具的解决方案比这更有效的,但这种感觉非常符合Python和避免了导入库只是一个列表操作的缘故。
Answer 3:
你可以找到一个很好的答案itertools'食谱:
def flatten(listOfLists):
return list(chain.from_iterable(listOfLists))
(注:需要Python 2.6+)
Answer 4:
提出的问题flatmap
。 一些实现提出,但他们可能没有必要创建中间的列表。 下面是一个实现,对迭代器基地。
def flatmap(func, *iterable):
return itertools.chain.from_iterable(map(func, *iterable))
In [148]: list(flatmap(os.listdir, ['c:/mfg','c:/Intel']))
Out[148]: ['SPEC.pdf', 'W7ADD64EN006.cdr', 'W7ADD64EN006.pdf', 'ExtremeGraphics', 'Logs']
在Python 2.x中,使用itertools.map
到位的map
。
Answer 5:
你可以只是做了简单的:
subs = []
for d in dirs:
subs.extend(os.listdir(d))
Answer 6:
您可以通过普通的加法运算符串连列表:
>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
内置的功能sum
将在一个序列中添加的数量,并可选择从一个特定的值开始:
>>> sum(xrange(10), 100)
145
结合上面压平列表的列表:
>>> sum([[1, 2], [3, 4]], [])
[1, 2, 3, 4]
现在,您可以定义flatmap
:
>>> def flatmap(f, seq):
... return sum([f(s) for s in seq], [])
...
>>> flatmap(range, [1,2,3])
[0, 0, 1, 0, 1, 2]
编辑:我刚刚看到您的评论的批评另一个答案 ,我想这是正确的,Python将不必要的建设和垃圾收集大量小名单的这个解决方案。 这样,可不能说是最好的事情是,如果你已经习惯了函数式编程是非常简单和简洁的:-)
Answer 7:
import itertools
x=[['b11','b12'],['b21','b22'],['b31']]
y=list(itertools.chain(*x))
print y
itertools将从python2.3和更大的工作
Answer 8:
subs = []
map(subs.extend, (os.listdir(d) for d in dirs))
(但蚂蚁的回答是更好; +1为他)
Answer 9:
你可以尝试itertools.chain()
就像这样:
import itertools
import os
dirs = ["c:\\usr", "c:\\temp"]
subs = list(itertools.chain(*[os.listdir(d) for d in dirs]))
print subs
itertools.chain()
返回一个迭代,因此通过以list()
Answer 10:
谷歌给我带来了一个解决方案:
def flatten(l):
if isinstance(l,list):
return sum(map(flatten,l))
else:
return l
Answer 11:
您可以使用pyxtension :
from pyxtension.streams import stream
stream([ [1,2,3], [4,5], [], [6] ]).flatMap() == range(7)
Answer 12:
def flat_list(arr):
send_back = []
for i in arr:
if type(i) == list:
send_back += flat_list(i)
else:
send_back.append(i)
return send_back
Answer 13:
If listA=[list1,list2,list3]
flattened_list=reduce(lambda x,y:x+y,listA)
这将做。
文章来源: python list comprehensions; compressing a list of lists?