如何从列表推导而不是嵌套列表获得平坦的结果?

2025-01-03 08:41:00
admin
原创
96
摘要:问题描述:我有一个列表A,以及一个f接受 的项目A并返回列表的函数。我可以使用列表推导将 中的所有内容转换A为[f(a) for a in A],但这会返回一个列表列表。假设我的输入是[a1,a2,a3],结果为[[b11,b12],[b21,b22],[b31,b32]]。我怎样才能获得扁平列表[b11,b...

问题描述:

我有一个列表A,以及一个f接受 的项目A并返回列表的函数。我可以使用列表推导将 中的所有内容转换A[f(a) for a in A],但这会返回一个列表列表。假设我的输入是[a1,a2,a3],结果为[[b11,b12],[b21,b22],[b31,b32]]

我怎样才能获得扁平列表[b11,b12,b21,b22,b31,b32]?换句话说,在 Python 中,我怎样才能获得flatmap函数式编程语言或SelectMany.NET 中传统上所称的内容?

(在实际代码中,A是目录列表,fos.listdir。我想建立一个平面的子目录列表。)


另请参阅:如何从列表列表中创建平面列表?以解决在创建列表列表后将其平面化的更普遍问题。


解决方案 1:

你可以在单个列表推导中进行嵌套迭代:

[filename for path in dirs for filename in os.listdir(path)]

其至少在功能上等同于:

filenames = []
for path in dirs:
    for filename in os.listdir(path):
        filenames.append(filename)

解决方案 2:

>>> from functools import reduce  # not needed on Python 2
>>> list_of_lists = [[1, 2],[3, 4, 5], [6]]
>>> reduce(list.__add__, list_of_lists)
[1, 2, 3, 4, 5, 6]

itertools解决方案更有效,但感觉非常 Pythonic。

解决方案 3:

itertools您可以在食谱中找到很好的答案:

import itertools

def flatten(list_of_lists):
    return list(itertools.chain.from_iterable(list_of_lists))

解决方案 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

解决方案 5:

你可以直接这样做:

subs = []
for d in dirs:
    subs.extend(os.listdir(d))

解决方案 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 会用这个解决方案不必要地构建和垃圾收集大量较小的列表,这是正确的。所以可以说的最好的事情是,如果你习惯了函数式编程,它非常简单和简洁 :-)

解决方案 7:

subs = []
map(subs.extend, (os.listdir(d) for d in dirs))

(但 Ants 的答案更好;对他来说 +1)

解决方案 8:

import itertools
x=[['b11','b12'],['b21','b22'],['b31']]
y=list(itertools.chain(*x))
print y

itertools 适用于 python2.3 及更高版本

解决方案 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()

解决方案 10:

这是最简单的方法:

def flatMap(array):
  return reduce(lambda a,b: a+b, array) 

'a+b' 表示两个列表的连接

解决方案 11:

您可以使用pyxtension:

from pyxtension.streams import stream
stream([ [1,2,3], [4,5], [], [6] ]).flatMap() == range(7)

解决方案 12:

谷歌给我带来了下一个解决方案:

def flatten(l):
   if isinstance(l,list):
      return sum(map(flatten,l))
   else:
      return l

解决方案 13:

我一直在寻找flatmap并首先找到了这个问题。flatmap基本上是对原始问题要求的概括。如果您正在寻找一种简洁的方式来定义flatmap可求和的集合(例如列表),您可以使用

sum(map(f,xs),[])

它只比写作长一点

flatmap(f,xs)

但一开始可能不太清楚。

最明智的解决方案是将其作为flatmap编程语言中的一个基本函数,但只要它不是,您仍然可以使用更好或更具体的名称来定义它:

# `function` must turn the element type of `xs` into a summable type.
# `function` must be defined for arguments constructed without parameters.
def aggregate(function, xs):
    return sum( map(function, xs), type(function( type(xs)() ))() )

# or only for lists
aggregate_list = lambda f,xs: sum(map(f,xs),[])

不幸的是,字符串不可求和,因此它不适用于它们。

你可以这样做

assert( aggregate_list( lambda x: x * [x], [2,3,4] ) == [2,2,3,3,3,4,4,4,4] )

但你不能这样做

def get_index_in_alphabet(character):
    return (ord(character) & ~0x20) - ord('A')

assert(aggregate( lambda x: get_index_in_alphabet(x) * x, "abcd") == "bccddd")

对于字符串,您需要使用

aggregate_string = lambda f,s: "".join(map(f,s))  # looks almost like sum(map(f,s),"")

assert( aggregate_string( lambda x: get_index_in_alphabet(x) * x, "abcd" ) == "bccddd" )

这显然很乱,不同类型的函数需要不同的函数名,甚至语法。希望 Python 的类型系统将来能够得到改进。

解决方案 14:

您还可以使用该flatten函数numpy

import numpy as np

matrix = [[i+k for i in range(10)] for k in range(10)]
matrix_flat = np.array(arr).flatten()

numpy 文档flatten

解决方案 15:

为什么不能将flatten函数flat_map应用于任何使用生成器的可迭代对象?

def flatten(iters):
    for it in iters:
        for elem in it:
            yield elem

def flat_map(fn, it):
    return flatten(map(fn, it))

使用方法非常简单:

for e in flat_map(range, [1, 2, 3]):
    print(e, end=" ")
# Output: 0 0 1 0 1 2

作为一个有趣的琐事,你flatten也可以用递归的方式编写。分析留给感兴趣的读者吧!

def flatten(it):
    try:
        yield from next(it)
        yield from flatten(it)
    except StopIteration:
        pass

解决方案 16:

If listA=[list1,list2,list3]
flattened_list=reduce(lambda x,y:x+y,listA)

这样就可以了。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用