shi*_*iru 3 python algorithm recursion list
我试图编写一个函数来读取包含列表的列表,并返回相同的列表结构但没有元素.
def remove_from_list(l):
for e in l:
if isinstance(e, list):
remove_from_list(e)
else:
l.remove(e)
return l
Run Code Online (Sandbox Code Playgroud)
所以对于这样的输入:
[1, 2, [], [3,[4]], 5]
Run Code Online (Sandbox Code Playgroud)
我应该得到这样的东西:
[[], [[]]]
Run Code Online (Sandbox Code Playgroud)
我尝试了这些输入:
[1, 2, [], [3,[4]], 5]
[1, 2, [], [2,[3]], 2]
Run Code Online (Sandbox Code Playgroud)
得到这些输出:
[2, [], [[4]]]
[[], [[3]], 2]
Run Code Online (Sandbox Code Playgroud)
这是非常令人困惑的,因为两个列表的结构是相同的; 只有元素不同.因此,我不仅会犯错误,而且会得到另一个错误.帮助我的错误的功能和解释将非常感激.
这里的关键问题是for循环有一定数量的迭代,但是当你删除循环中的列表时,你就会缩小它们.因此,当列表变小时,循环指针保持固定.有一次,循环没有机会完成迭代.
选项1
作为一个简单的修复,您可以在函数内创建一个新列表.这应该更简单,并且不会改变您的原始列表.
def remove_from_list(l):
r = []
for e in l:
if isinstance(e, list):
r.append(remove_from_list(e))
return r
Run Code Online (Sandbox Code Playgroud)
>>> remove_from_list([1, 2, [], [3,[4]], 5])
[[], [[]]]
Run Code Online (Sandbox Code Playgroud)
此外,由于您只是附加空结构,因此这应该比创建数据副本和后续删除调用更快.
选项2
以wim的思想为基础,反向迭代并使用,del如果你想改变列表的位置.
def remove_from_list(l):
r = []
for i in range(len(l) - 1, -1, -1):
if isinstance(l[i], list):
remove_from_list(l[i])
else:
del l[i]
Run Code Online (Sandbox Code Playgroud)
>>> l = [1, 2, [], [3,[4]], 5]
>>> remove_from_list(l)
>>> l
[[], [[]]]
Run Code Online (Sandbox Code Playgroud)
从良好实践的角度来看,我建议要么返回副本,要么在没有返回的情况下进行修改,但不能同时修改.
您可以执行时间比较,以确定哪种方法可以更快地处理数据.
一,设置 -
def remove_from_list(l):
r = []
for e in l:
if isinstance(e, list):
r.append(remove_from_list(e))
return r
def remove_from_list_reverse_del(l):
r = []
for i in range(len(l) - 1, -1, -1):
if isinstance(l[i], list):
remove_from_list(l[i])
else:
del l[i]
def remove_from_list_copy(l):
for e in l[:]: # make a copy by slicing
if isinstance(e, list):
remove_from_list_copy(e)
else:
l.remove(e)
return l
y = [1, 2, [], [3,[4]], 5]
z = copy.deepcopy(y * 10000)
Run Code Online (Sandbox Code Playgroud)
接下来,时间 -
%timeit remove_from_list(z)
19.3 ms ± 334 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Run Code Online (Sandbox Code Playgroud)
%%timeit
z2 = copy.deepcopy(z) # copying because this function mutates the original
remove_from_list_reverse_del(z2)
78.6 ms ± 157 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)
虽然创造时浪费了很大一部分时间z2.