在python中,reduce
接受一个只接受两个参数的函数。
有没有什么很好的方法让reduce
可以接受两个以上的参数?
例如:
from operator import add
list = [1,add,2,add,3,add,4]
func = lambda operand1,operator,operand2: operator(operand1,operand2)
reduce(func,list) # mock reduce. Expected result is 10(1+2+3+4=10)
编辑:
reduce3
函数用于计算抽象语法树的结果。
AST的每个子节点可以是一个节点,也可以是另一个树。为了简单起见,假设叶子节点只能是数字,加法符号(+
)或减法符号(-
).To计算结果,一种直观的想法是首先计算出每个节点的结果(可以通过递归调用该方法实现),然后将它们组合在一起。例如,下面是一个简单的AST:
Tree(
Node(1),
Node("+"),
Tree(
Node(2),
"+",
Node(3)
),
Node("-"),
Node(4)
)
在递归之后,我们得到以下结果。
如果有一个带3个参数的reduce
,我们可以很容易地组合结果。
Tree(
Node(1),
Node("+"),
Node(5)
Node("-"),
Node(4)
)
发布于 2021-12-04 16:04:28
这给出了没有3个参数的确切结果。如果参数类似于1, add
,它将为每个参数创建一个分部函数;如果参数类似于partial,2
,它将调用该函数
from operator import add
from functools import reduce, partial
lst = [1,add,2,add,3,add,4]
def operation_reduce(x, y):
if callable(x):
return x(y)
else:
return partial(y, x)
print(reduce(operation_reduce, lst)) #10
发布于 2021-12-04 16:06:38
reduce
不能更改,但您可以提供一个处理不同输入的callable:
from functools import reduce
from operator import add, sub
L = [1, add, 2, add, 3, add, 4, sub]
class Reducer:
def __init__(self):
self.pending = 0
def __call__(self, total, value):
if callable(value):
total = value(total, self.pending)
else:
self.pending = value
return total
func = Reducer()
result = reduce(func, L, 0)
print(result)
或者,您可以在元组中对输入进行批处理,并使用可以处理这些输入的可调用函数
def reducer(total, next_):
value, operation = next_
return operation(total, value)
result = reduce(reducer, zip(L[::2], L[1::2]), 0)
print(result)
发布于 2021-12-04 16:33:41
我很有兴趣知道你想要的用例是什么,因为我认为reduce接受超过2个参数是不优雅的,就这样。这是我的理由(尽管在抽象上有点困难,没有具体的用例):
假设reducing操作采用3个参数,如您的示例所示。让我们也显式地设置初始累加器,reduce3(func,list,acc)。然后在每次对func的调用中:
中始终是偶数位置
函数处理列表中的偶数位置元素的方式与处理奇数位置元素的方式不同。如果奇数和偶数位置的元素是不同类型的,我们就会需要这样的reduce3函数!*示例中就是这种情况。在一个列表中混合不同类型的元素需要更加小心,以免出错(弄乱了2个元素的顺序,并导致reduce3中断),通常应该避免使用IMO。
修改您的示例:
list = [2,3,4] # we'l include 1 as initial acc
ops = [add, add, add]
func = lambda acc, pair : pair[0](acc, pair[1])
reduce(func, zip(ops, list), 1) # result is 10(1+2+3+4=10)
减少元组列表是您问题的一般解决方案。如果数学表达式是你想要计算的,你应该考虑它们的树结构,当折叠成一个列表时,它就会丢失。
编辑:
实际上,您希望计算数学表达式。请考虑更改解析这些表达式的方式,以便在本例中AST如下所示:
Tree("-",
Tree("+",
Node(1),
Tree("+",
Node(2),
Node(3))),
Node(4))
# -
# / \
# + 4
# / \
# 1 +
# / \
# 2 3
也就是说,内部节点总是使用二进制操作进行标记,并且只有leafs携带数字。现在,将树减少为一个值是微不足道的,但以解析为代价来完成大部分工作。
# Here assuming some specifics of the Tree and Node classes.
# strToOpt is mapping of operation symbols to functions.
def evaluate(expr): # expr : Tree or Node
if (isinstance(expr, Node)): # expr : Node
return expr.x
else: # expr : Tree
return strToOp[expr.op](evaluate(expr.left), evaluate(expr.right))
如果允许使用非二叉树节点,则将"else“分支替换为reduce like reduce(strToOpt[expr.op], expr.children)
。
我理解这是非常不同的方法。如果你想坚持下去,Reduce3应该不会那么难实现,对吧?在python中寻找一些从头开始解析数学的帮助,你可以看看我的旧项目,但它是一个学生(我)写的业余代码。另一方面,不分享是不公平的,在这里你可以去:
*不一定是编程意义上的不同类型,但对我们来说肯定是不同的类型或含义。
https://stackoverflow.com/questions/70226987
复制相似问题