应用三参数函数“减少”列表的pythonic方法是啥?
Posted
技术标签:
【中文标题】应用三参数函数“减少”列表的pythonic方法是啥?【英文标题】:Which is the pythonic way to 'reduce' a list applying a three-parameter function?应用三参数函数“减少”列表的pythonic方法是什么? 【发布时间】:2021-12-08 13:20:47 【问题描述】:我已经习惯了类似 FP/haskell 的 reduce 概念,已经在 Python 中作为内置库实现:
from functools import reduce
lst = [1,2,3,4,5]
reduce(lambda x, y: x*y, lst)
# result: 120
但这不适用于例如具有三个参数的 lambda:
from functools import reduce
lst = [1,2,3,4,5]
reduce(lambda x, y, z: x*y+z, lst)
# expected result: (1*2+3) * 4 + 5
# actual result:
# TypeError: <lambda>() missing 1 required positional argument: 'z'
基本原理是保持“前一个结果是下一个参数”的规则。
是否有内置的实现,或功能结构的巧妙/简单组合来实现这样的目标?
ps。当心pseudo-duplicates
【问题讨论】:
【参考方案1】:一个相当简单的实现是
import inspect
def nreduce(fn, lst):
nargs = len(inspect.signature(fn).parameters)
args = list(lst)
while len(args) >= nargs:
next_args = [args.pop(0) for x in range(nargs)]
args.insert(0, fn(*next_args))
return args
lst = [1, 2, 3, 4, 5]
print(nreduce(lambda x, y, z: x * y + z, lst))
如果你想花哨,你可以使用deque
使刚刚减少的值更快地插入到列表的左侧:
import collections
def nreduce(fn, lst):
nargs = len(inspect.signature(fn).parameters)
arg_queue = collections.deque(lst)
while len(arg_queue) >= nargs:
next_args = [arg_queue.popleft() for x in range(nargs)]
arg_queue.appendleft(fn(*next_args))
return list(arg_queue)
如果lst
的长度不能被fn
的元数整除,那么剩余的元素也会被返回。
另一个实现,它可以与任何可迭代对象一起工作,而无需复制到其他列表或队列中(不会返回 lst
的其余部分,只是它消耗的值):
def nreduce(fn, lst):
nargs = len(inspect.signature(fn).parameters)
lst_iter = iter(lst)
next_args = []
while True:
try:
while len(next_args) < nargs:
next_args.append(next(lst_iter))
except StopIteration:
break
next_args = [fn(*next_args)]
return next_args
【讨论】:
以上是关于应用三参数函数“减少”列表的pythonic方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章