什么是自扁平化嵌套列出了推荐的方式编译包的弃用 ?
>>> from compiler.ast import flatten
>>> flatten(["junk",["nested stuff"],[],[[]]])
['junk', 'nested stuff']
我知道有对列表压扁了几个堆栈溢出的答案,但我希望能为Python化,标准包“一个,最好只有一种,明显的方式”来做到这一点。
什么是自扁平化嵌套列出了推荐的方式编译包的弃用 ?
>>> from compiler.ast import flatten
>>> flatten(["junk",["nested stuff"],[],[[]]])
['junk', 'nested stuff']
我知道有对列表压扁了几个堆栈溢出的答案,但我希望能为Python化,标准包“一个,最好只有一种,明显的方式”来做到这一点。
您所陈述的功能需要一个嵌套列表,而变平是进入一个新的列表。
扁平化的任意嵌套表到一个新的列表,你希望这个工程上的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)
itertools.chain
是压扁任何嵌套迭代一个级别的最佳解决方案-比任何纯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
请记住,使用basestring
在2.X过str
,并for subel in flatten(el): yield el
,而不是yield from flatten(el)
预3.3。
正如在评论中指出,我认为这是核选择,并有可能导致更多的问题比它解决的。 相反,最好的办法是让你的输出更规则(包含一个项目输出仍然给它作为一个项目的元组,例如),并在那里被引入,而不是所有在最后一个级别做定期的扁平化。
这将产生更多的逻辑,可读性,也更容易与代码工作。 当然,有些情况下,你需要做这种扁平化的情况下(如果数据是从什么地方你不能惹的到来,所以你没有选择,只能把它的不良结构格式),在这种情况下,可能需要这样的解决方案,但在一般情况下,它可能是一个坏主意。
您可以使用拼合从功能funcy库:
from funcy import flatten, isa
flat_list = flatten(your_list)
您也可以明确指定哪些值如下:
# Follow only sets
flat_list = flatten(your_list, follow=isa(set))
在偷看它的实现 ,如果你想要一个algorythm。
我的丑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
有与任意嵌套的列表中没有内置的方法,但是这样的事情...
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']
...将列表和元组工作。 如果你想支持您可以在使用任何对象for item in object
的表情,那么它可能是最好使用鸭打字像这样...
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]
专为递归:Python的3.6
def flatten(lst):
"""Flattens a list of lists"""
return [subelem for elem in lst
for subelem in elem]
定义你的类型的列表,然后使用任何内建的检查