【算法题】不定列表求和
问题
在一个嵌套了多个元素为数字或列表 (列表中也是数字或列表) 的列表中,求出所有数字的和。
例如:[1, [2, [3, [4, 5]]]]
的和为 15,[1, 2, 3, 4, 5]
的和也为 15。
分析
通过遍历每一个元素,如果发现这个元素不是列表,就把它累加,否则继续遍历这个元素直到找到数字。可以采用递归的方式来求解。
def sum_ulist(exp):
sum = 0
for i in exp:
sum += i if type(i) != list else sum_ulist(i)
return sum
可以看到最后的程序非常短小,运行如下:
>>> sum_ulist([1, [2, [3, [4, 5]]]])
15
>>> sum_ulist([1, 2, 3, 4, 5])
15
思考
还是一个不定嵌套层数的列表,这次不进行求和,而是把其中的所有数字都取出来,最后放在一个列表中返回。
与上面类似,不过上面的求和在每一次函数调用中只关注当前层级的总和即可,而这边的递归需要把数字都放在同一个列表中,可以利用默认参数的一个特性来解决。
我们之前提到,默认参数必须设置为不可变,否则会带来一些问题:当你调用此函数却不指定默认参数的值时,它会自动使用函数第一次调用中默认参数的对象,如果这个对象发生了改变,可能达不到我们预期的效果。
举个例子:
def a(li=[]):
li.append(1)
return li
>>> a()
[1]
>>> a()
[1, 1]
>>> a()
[1, 1, 1]
这种情况在很多时候都不是我们想要的,这边却可以利用这个特性:
def add_ulist(exp, tem_li=[]):
for i in exp:
tem_li.append(i) if type(i) != list else add_ulist(i)
return sum
通过在 else 语句后面的递归中不指定默认参数,我们就让后面的函数调用都只操作第一次函数调用时初始化的 tem_li 对象了,少写了几个字母 :)
运行如下:
>>> add_ulist([1, [2, [3, [4, 5]]], [6, [7, 8]]])
[1, 2, 3, 4, 5, 6, 7, 8]
当然,在 else 语句后面的递归中将这次函数获得的 tem_li 列表传给默认参数也可以:
def add_ulist(exp, tem_li=[]):
for i in exp:
tem_li.append(i) if type(i) != list else add_ulist(i, tem_li)
return sum
最后,如果弄不清楚默认参数的奇妙性质的话,还是老老实实将默认参数设置为不可变对象吧:
def add_ulist(exp, tem_li=None):
if tem_li is None:
tem_li = []
for i in exp:
tem_li.append(i) if type(i) != list else add_ulist(i, tem_li)
return sum
这个必须点赞👍