Python列表内涵; 压缩列表的列表?(python list comprehensions;

2019-06-24 20:11发布

家伙。 我试图找到最优雅的解决一个问题,不知道是否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?