Python 3替换已弃用的compiler.ast flant函数
自发布以来,建议采用什么方法展平嵌套列表 我知道列表展平有一些堆栈溢出的解决方案,但我希望pythonic的标准包“一种,最好只有一种,明显的方法”可以做到这一点。是将任何嵌套的iterable展平到一个级别的最佳解决方案-它比任何纯python解决方案都高效 这就是说,它将在所有的iterables上工作,因此,如果您希望避免它使字符串变平,则需要进行一些检查 同样,它也不会神奇地变平到任意深度。这就是说,一般来说,这样一个通用的解决方案是不需要的-相反,最好保持您的数据结构化,这样它就不需要以这种方式扁平化 编辑:我认为,如果必须进行任意展平,这是最好的方法:Python 3替换已弃用的compiler.ast flant函数,python,python-3.x,flatten,Python,Python 3.x,Flatten,自发布以来,建议采用什么方法展平嵌套列表 我知道列表展平有一些堆栈溢出的解决方案,但我希望pythonic的标准包“一种,最好只有一种,明显的方法”可以做到这一点。是将任何嵌套的iterable展平到一个级别的最佳解决方案-它比任何纯python解决方案都高效 这就是说,它将在所有的iterables上工作,因此,如果您希望避免它使字符串变平,则需要进行一些检查 同样,它也不会神奇地变平到任意深度。这就是说,一般来说,这样一个通用的解决方案是不需要的-相反,最好保持您的数据结构化,这样它就不需要
import collections
def flatten(iterable):
for el in iterable:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
yield from flatten(el)
else:
yield el
记住在2.x中使用basestring
overstr
,在展平(el)中为subel使用:产生el
,而不是3.3之前的从展平(el)产生收益
正如评论中所指出的,我认为这是一种核选择,可能会造成比解决问题更多的问题。相反,最好的方法是使输出更加规则(例如,包含一个项的输出仍然以一个项元组的形式提供),并在引入该项的地方按一个级别进行规则展平,而不是在最后进行所有展平
这将产生更具逻辑性、可读性和更易于使用的代码。当然,在某些情况下,您需要进行这种展平(如果数据来自您无法处理的地方,因此您别无选择,只能采用结构不良的格式),在这种情况下,可能需要这种解决方案,但一般来说,这可能是个坏主意。您所述的函数获取一个嵌套列表并将其展平为一个新列表
要将任意嵌套的列表展平为新列表,这将在Python 3上正常工作,正如您所期望的:
import collections
def flatten(x):
result = []
for el in x:
if isinstance(x, collections.Iterable) and not isinstance(el, str):
result.extend(flatten(el))
else:
result.append(el)
return result
print(flatten(["junk",["nested stuff"],[],[[]]]))
印刷品:
['junk', 'nested stuff']
如果您想要一台具有相同功能的发电机:
def flat_gen(x):
def iselement(e):
return not(isinstance(e, collections.Iterable) and not isinstance(e, str))
for el in x:
if iselement(el):
yield el
else:
for sub in flat_gen(el): yield sub
print(list(flat_gen(["junk",["nested stuff"],[],[[[],['deep']]]])))
# ['junk', 'nested stuff', 'deep']
对于Python 3.3及更高版本,请使用以下命令代替循环:
def flat_gen(x):
def iselement(e):
return not(isinstance(e, collections.Iterable) and not isinstance(e, str))
for el in x:
if iselement(el):
yield el
else:
yield from flat_gen(el)
对于具有任意嵌套的列表,没有内置的方法,但是类似这样的东西
def flatten(l):
for i in l:
if isinstance(i, (list, tuple)):
for ii in flatten(i):
yield ii
else:
yield i
>>> l = ["junk",["nested stuff"],[],[[]]]
>>> list(flatten(l))
['junk', 'nested stuff']
def flatten(l):
for i in l:
if isinstance(i, (str, bytes)):
yield i
else:
try:
for ii in flatten(i):
yield ii
except TypeError:
yield i
>>> l = ["junk",["nested stuff"],[],[[]]]
>>> list(flatten(l))
['junk', 'nested stuff']
…适用于列表和元组。如果您想支持在对象
表达式的for item中可以使用的任何对象,那么最好像这样使用duck类型
def flatten(l):
for i in l:
if isinstance(i, (list, tuple)):
for ii in flatten(i):
yield ii
else:
yield i
>>> l = ["junk",["nested stuff"],[],[[]]]
>>> list(flatten(l))
['junk', 'nested stuff']
def flatten(l):
for i in l:
if isinstance(i, (str, bytes)):
yield i
else:
try:
for ii in flatten(i):
yield ii
except TypeError:
yield i
>>> l = ["junk",["nested stuff"],[],[[]]]
>>> list(flatten(l))
['junk', 'nested stuff']
…这比检查isinstance(el,Iterable)
稍微健壮一些,因为它无法处理某些情况,例如
class Range10:
def __getitem__(self, index):
if index >= 10:
raise IndexError
return index
>>> import collections
>>> r10 = Range10()
>>> isinstance(r10, collections.Iterable)
False
>>> list(Range10())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我的丑陋
while chain
解决方案,只是为了好玩:
from collections import Iterable
from itertools import chain
def flatten3(seq, exclude=(str,)):
sub = iter(seq)
try:
while sub:
while True:
j = next(sub)
if not isinstance(j, Iterable) or isinstance(j, exclude):
yield j
else:
sub = chain(j, sub)
break
except StopIteration:
return
您可以使用库中的函数:
还可以显式指定要遵循的值:
# Follow only sets
flat_list = flatten(your_list, follow=isa(set))
如果您想要一个算法,请看一看。为递归构建:Python 3.6
def flatten(lst):
"""Flattens a list of lists"""
return [subelem for elem in lst
for subelem in elem]
在列表中定义您的类型,并使用any内置项检查另一个递归:Python 3.6。适用于列表/字符串/数字的复杂嵌套列表以及以下所有内容的组合:
def list_flattener(nestedList):
nonListElems=[]
listElems=[]
nestedListCounter=0
for nc in range(len(nestedList)):
if type(nestedList[nc])==list:
nestedListCounter+=1
listElems=nestedList[nc]+listElems
else:nonListElems.append(nestedList[nc])
if nestedListCounter==0: return (nestedList)
else:
nestedList=listElems+nonListElems
return list_flattener(nestedList)
请参见下面的示例:
>>> nestedList=['arash',[[1,'anotherOne',[12,'stringX',['kave']]], 'stringY']]
>>> list_flattener(nestedList)
['kave', 12, 'stringX', 1, 'anotherOne', 'stringY', 'arash']
谢谢这可能是一个愚蠢的澄清,但你有一个如何联合它的建议吗<代码>>>>itertools.chain([[“垃圾”[“嵌套的东西”],[],[[[]]]])我通常使用列表(iterable)来联合它,但如果我在这种情况下这样做,我将得到一个非平面列表!联合?我真的不确定那是什么意思<代码>列表(iterable)是从任意iterable中获取列表的最佳方式。使用上面的列表,我可以得到:
>>>列表(itertools.chain([[“垃圾”,“嵌套的东西],[],[],[],[[[]]]])
与扁平化()
相比,扁平化()[“垃圾”,“嵌套的东西”]
chain()
将iterable作为每个参数,如果要传入iterable,请使用chain.from\u iterable()
。请注意,它将(如回答中所述)仅移除一层嵌套。除此之外,制作一个通用工具并不真正值得,因为不同的情况会将不同的iterables视为需要展平的对象(例如字符串)。对不起,我可能还没有理解它:>>列表(itertools.chain.from_iterable([[“垃圾”,“嵌套的东西],[],[]]])
给了我[“垃圾”,“嵌套的东西],[],[],[]]
-1-对列表和元组进行类型检查会使这一点变得非常不灵活。@Lattyware的问题是:“建议用什么方法展平嵌套列表…”@Lattyware对第二个选项有何评论?对不起,我是在回答我自己的问题。我的问题是Python是一种灵活的语言,而类型检查通常是一种糟糕的解决方案。询问者可能只考虑列表,但在某些情况下使用一些自定义数据结构,其功能类似于列表,但不能与代码一起使用。Python是为duck类型设计的,因此,尽管有其他类型的功能,但只适用于某些类型的函数非常烦人,而且通常是一个坏主意。我非常确定Sequence
需要定义\u len\u()
,而且可能会测试它的可伸缩性。构建这样的列表是一个非常糟糕的解决方案,生成器会更合适。我会说“非常糟糕的解决方案”有点强。如果嵌套列表相对较小,则生成生成器的速度可能较慢。这取决于需要。我把两者都贴了出来。在一个小列表上创建生成器可能会慢一些,但是当它很小的时候,时间差就无关紧要了。然而,当它很大的时候,它很可能就足够了。不管怎样,最好只使用生成器,这样更容易阅读。除此之外,hasattr(e,“\uuuuu iter”
通常是一种更好的检查方法,使用Iterable
ABC进行检查-这样可读性更强。我开始非常喜欢funcy。谢谢你的提示。