为啥扁平列表中的空白项目
Posted
技术标签:
【中文标题】为啥扁平列表中的空白项目【英文标题】:Why blank items in flattened list为什么扁平列表中的空白项目 【发布时间】:2018-05-14 17:11:09 【问题描述】:我正在尝试使用递归函数来展平可能包含子列表项的已发送列表:
def myflatten(slist, outlist=[]):
for sl in slist:
if type(sl) == list:
outlist.append(myflatten(sl, outlist))
else:
outlist.append(sl)
return outlist
print("myflatten list=", myflatten([1,[5,6,7],3,4,[7,8,9]]))
输出:
myflatten list= [1, 5, 6, 7, [...], 3, 4, 7, 8, 9, [...]]
为什么每个子列表都会收到[...]
,我怎样才能避免收到这个?感谢您的帮助。
【问题讨论】:
[...]
表示列表包含自身
我认为问题在于您正在更新default
对outlist
的引用。例如,如果你调用myflatten([1])
,然后调用myflatten([2])
,你会得到[1, 2]
这不是问题的原因,但请注意那里的函数定义中的Default mutable gotcha。即使您的代码正常工作,如果您多次调用它,它也可能会产生令人惊讶的结果。
@turbulencetoo 很有趣!以前没见过,每天都学点新东西!
@Kevin 实际上,我认为这是问题的原因。这是一个递归调用。
【参考方案1】:
另一个不使用list.extend
的选项。我会重新排列您的代码,并尽量避免使用默认参数:
def myflatten(slist):
flat = []
if isinstance(slist, list):
for item in slist:
flat += myflatten(item)
else:
flat.append(slist)
return flat
【讨论】:
@rnso 确实如此。效率上不知道有没有区别,反正应该不会太大。【参考方案2】:您创建了一个无限列表。列表中的[...]
条目指向列表本身。详情请见this answer。
这是因为当您进行递归调用时,您传入outlist
对象本身,然后将其返回并附加到自身。一个微妙的问题!但是很容易解决;您将希望使用=
进行递归调用,而不是append
。或者extend
,然后传入一个空列表。
def myflatten(slist):
outlist = []
for sl in slist:
if type(sl) == list:
outlist.extend(myflatten(sl))
else:
outlist.append(sl)
return outlist
你甚至可以去掉一个参数,这很好。
【讨论】:
【参考方案3】:现有的答案很好地解释了为什么会出现 [...] 自引用,但他们建议的代码修订对解决等待咬你的 default mutable argument gotcha 没有任何作用。
这是一个不需要 outlist
参数的解决方案:
def myflatten(slist):
outlist = []
for sl in slist:
if isinstance(sl, list):
outlist.extend(myflatten(sl))
else:
outlist.append(sl)
return outlist
print("myflatten list=", myflatten([1,[5,6,7],3,4,[7,8,9]]))
【讨论】:
是的,它运行良好。extend
是一个有用的功能。
保留空白accumulator
作为参数在 Scheme/Racket/Lisp 派生语言中很常见(如在 ***.com/questions/29425944/… 中)【参考方案4】:
问题是 myflatten 正在返回一个列表。因此,当您将 myflatten 的结果附加到 outlist 时,它会附加一个列表。尝试设置 outlist 等于 myflatten 的结果:
def myflatten(slist, outlist=[]):
for sl in slist:
if type(sl) == list:
outlist = myflatten(sl, outlist) #HERE IS THE CHANGE
else:
outlist.append(sl)
return outlist
print("myflatten list=", myflatten([1,[5,6,7],3,4,[7,8,9]]))
【讨论】:
但是我发现后续调用会不断添加到由先前调用该函数创建的 outlist 中。如何纠正? @rnso 你能给我举个例子哦,你的意思是什么? 在你的函数上尝试print(myflatten([1])); print(myflatten([2]))
。您将得到 [1,2]
作为第二个命令的输出。
有趣,学到了新东西。凯文的答案效果更好,因为它不使用 outlist 作为参数。我可以更新这个,但由于他的回答有效,除非你愿意,否则我不会更新。
看这个:***.com/questions/1132941/…以上是关于为啥扁平列表中的空白项目的主要内容,如果未能解决你的问题,请参考以下文章
扁平化和过滤 ansible 中的复杂结构 - dict 列表中的 dict
扁平化(不规则)Python 中关于 Pandas Dataframes 的列表列表