在减少python中的列表时,我考虑过创建多列表缩减并编写以下代码段。
def multiply(a, b): return a * b
def recursive_reduce(reduce_func, *args):
ret_val = reduce(reduce_func, *args)
if type(ret_val) == list:
ret_val = recursive_reduce(reduce_func, ret_val)
return ret_val
a = [1, 1, 3]
b = [4, 5, 6]
recursive_reduce(multiply, a, b)
这很有效。但是我想知道根据返回值的类型定义迭代逻辑是否是pythonic。
我们是否有其他方式以更优雅的方式实现递归递减?
答案 0 :(得分:3)
我认为你要做的是做一个递归版本的reduce。
def rreduce(f, init, default=None):
if default is None:
default = init[0]
init = init[1:]
if len(init) == 0:
return default
return rreduce(f, init[1:], f(default, init[0]))
>>> rreduce(lambda a, b: a*b, range(1,10))
362880
>>> rreduce(lambda a, b: a+b, ['t', 'a', 'c', 'o'])
'taco'
虽然递归很棒,但这不是Python reduce
类型函数的首选方法,因为它很慢,你会遇到 STACK OVERFLOW (HAA)
>>> rreduce(lambda a, b: a + [b], list(range(1, 10000)), [])
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-41-7dc07c5d9246> in <module>()
----> 1 rreduce(lambda a, b: a + [b], list(range(1, 10000)), [])
<ipython-input-33-37206eb8e39f> in rreduce(f, init, default)
5 if len(init) == 0:
6 return default
----> 7 return rreduce(f, init[1:], f(default, init[0]))
... last 1 frames repeated, from the frame below ...
<ipython-input-33-37206eb8e39f> in rreduce(f, init, default)
5 if len(init) == 0:
6 return default
----> 7 return rreduce(f, init[1:], f(default, init[0]))
RecursionError: maximum recursion depth exceeded in comparison
回答你的实际问题......
def lreduce(f, init, default=None):
if default is None:
return reduce(lambda x, a: x + [reduce(f, a)], init, [])
else:
return reduce(lambda x, a: x + [reduce(f, a, default)], init, [])
将reduce
列表列表。
>>> lreduce(lambda a, b: a + b, [range(10), range(10), range(10)])
[45, 45, 45]
if/else
之所以必要,是因为reduce
作为builtin
不接受关键字参数:
In [56]: reduce(function=lambda a, b: a + b, sequence=range(10), initial=0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-56-9fa3ed177831> in <module>()
----> 1 reduce(function=lambda a, b: a + b, sequence=range(10), initial=0)
TypeError: reduce() takes no keyword arguments
然后如果你想再往前走一步......
def lreduceall(f, init, default=None):
if default is None:
return reduce(f, reduce(lambda x, a: x + [reduce(f, a)], init, []))
else:
return reduce(f, reduce(lambda x, a: x + [reduce(f, a, default)], init, []), default)
最后:
>>> lreduceall(lambda a, b: a + b, [range(10), range(10), range(10)])
135