我需要递归地压缩列表:
在列表显示之前:
L=[1,[2,[‘a’,(3,’b’)]],(5,6),([11,22])]
后:
Lflat=[1,2,’a’,(3,’b’),(5,6),([11,22])]
我遇到了我的代码问题(lst1是一个空的lst1)
def list_flatten(lst,lst1):
for item in lst:
if type(item) == tuple:
print(item)
lst1.append(item)
elif type(item) == list:
list_flatten(item,lst1)
else:
lst1.append(item)
return lst1
返回以下内容:
输出:[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
这让我发现([])被认为是一个列表,而不是一个元组。
现在我的问题如下:
答案 0 :(得分:2)
您的list_flatten
函数会改变lst1
参数,因此您根本不需要返回任何内容。你可以这样称呼它:
L = [1,[2,['a',(3,'b')]],(5,6),([11,22])]
def list_flatten(lst, lst1):
for item in lst:
if isinstance(item, list):
list_flatten(item, lst1)
else:
lst1.append(item)
Lflat = []
list_flatten(L, Lflat)
print(Lflat)
<强>输出强>
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
建议使用isinstance
而不是type
,因为这会使代码更加通用:它也可以使用从list
派生的对象。
我们可以重新编写该功能,以便您不需要传递lst1
:
def list_flatten(lst, lst1=None):
if lst1 is None:
lst1 = []
for item in lst:
if isinstance(item, list):
list_flatten(item, lst1)
else:
lst1.append(item)
return lst1
Lflat = list_flatten(L)
print(Lflat)
我们给lst1
一个默认值None
,在递归的顶层我们将名称lst1
重新绑定到一个空列表以收集结果。
我们无法为lst1
提供默认值[]
。这是因为默认args是在编译函数时创建的,而不是在函数被调用时创建的,如果我们给lst1
一个默认值[]
,那么每个调用都会使用相同的列表。它看起来像我们第一次使用list_flatten
时所做的那样,但是在后续调用中它不会按预期运行。这是一个简短的演示。
L = [1,[2,['a',(3,'b')]],(5,6),([11,22])]
def list_flatten(lst, lst1=[]):
for item in lst:
if isinstance(item, list):
list_flatten(item, lst1)
else:
lst1.append(item)
return lst1
Lflat = list_flatten(L)
print(Lflat)
Lflat = list_flatten(L)
print(Lflat)
<强>输出强>
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22, 1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
如您所见,lst1
在第一次通话时保留了其内容。有关此重要主题的详细信息,请参阅“Least Astonishment” and the Mutable Default Argument。有时候这种行为是可取的,但在这种情况下,在你的代码中添加一条你有意使用可变默认参数的评论是明智的。
另一种方法是将list_flatten
放入生成器,并将其输出收集到列表中:
def list_flatten(lst):
for item in lst:
if isinstance(item, list):
yield from list_flatten(item)
else:
yield item
Lflat = list(list_flatten(L))
print(Lflat)
在最新版本的Python中,您可以将list(list_flatten(L))
替换为[*list_flatten(L)]
。
Python 2没有yield from
,但你可以用以下代码替换该行:
for u in list_flatten(item):
yield u
如果您实际上不需要列表,可以像这样调用生成器:
for u in list_flatten(L):
print(u)
<强>输出强>
1
2
a
(3, 'b')
(5, 6)
11
22
答案 1 :(得分:1)
您可以注意到您需要的是:
在Python代码中,它会导致:
def flatten(L):
if len(L) == 0: return L
elif len(L) == 1 and not isinstance(L[0], list): return L
else:
return (flatten(L[0] if isinstance(L[0], list)
else [L[0]]) + flatten(L[1:]))
它按预期给出:
>>> L = [1, 2, 'a', (3, 'b'), (5, 6), ([11, 22],)]
>>> flatten(L)
[1, 2, 'a', (3, 'b'), (5, 6), ([11, 22],)]