首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在Python中让reduce函数带三个参数?

如何在Python中让reduce函数带三个参数?
EN

Stack Overflow用户
提问于 2021-12-04 15:33:26
回答 3查看 144关注 0票数 1

在python中,reduce接受一个只接受两个参数的函数。

有没有什么很好的方法让reduce可以接受两个以上的参数?

例如:

代码语言:javascript
代码运行次数:0
运行
复制
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:

代码语言:javascript
代码运行次数:0
运行
复制
Tree(
    Node(1),
    Node("+"),
    Tree(
        Node(2),
        "+",
        Node(3)
    ),
    Node("-"),
    Node(4)
)

在递归之后,我们得到以下结果。

如果有一个带3个参数的reduce,我们可以很容易地组合结果。

代码语言:javascript
代码运行次数:0
运行
复制
Tree(
    Node(1),
    Node("+"),
    Node(5)
    Node("-"),
    Node(4)
)
EN

回答 3

Stack Overflow用户

发布于 2021-12-04 16:04:28

这给出了没有3个参数的确切结果。如果参数类似于1, add,它将为每个参数创建一个分部函数;如果参数类似于partial,2,它将调用该函数

代码语言:javascript
代码运行次数:0
运行
复制
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
票数 2
EN

Stack Overflow用户

发布于 2021-12-04 16:06:38

reduce不能更改,但您可以提供一个处理不同输入的callable:

代码语言:javascript
代码运行次数:0
运行
复制
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)

或者,您可以在元组中对输入进行批处理,并使用可以处理这些输入的可调用函数

代码语言:javascript
代码运行次数:0
运行
复制
def reducer(total, next_):
    value, operation = next_
    return operation(total, value)


result = reduce(reducer, zip(L[::2], L[1::2]), 0)
print(result)
票数 2
EN

Stack Overflow用户

发布于 2021-12-04 16:33:41

我很有兴趣知道你想要的用例是什么,因为我认为reduce接受超过2个参数是不优雅的,就这样。这是我的理由(尽管在抽象上有点困难,没有具体的用例):

假设reducing操作采用3个参数,如您的示例所示。让我们也显式地设置初始累加器,reduce3(func,list,acc)。然后在每次对func的调用中:

  • 第一个参数通常是累加器,
  • 第二个参数始终是列表中奇数位置的元素,
  • 第三个参数在列表

中始终是偶数位置

函数处理列表中的偶数位置元素的方式与处理奇数位置元素的方式不同。如果奇数和偶数位置的元素是不同类型的,我们就会需要这样的reduce3函数!*示例中就是这种情况。在一个列表中混合不同类型的元素需要更加小心,以免出错(弄乱了2个元素的顺序,并导致reduce3中断),通常应该避免使用IMO。

修改您的示例:

代码语言:javascript
代码运行次数:0
运行
复制
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如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
Tree("-", 
    Tree("+",
        Node(1), 
        Tree("+", 
            Node(2), 
            Node(3))), 
    Node(4))
#       -
#      / \
#     +   4
#    / \
#   1   +
#      / \
#     2   3

也就是说,内部节点总是使用二进制操作进行标记,并且只有leafs携带数字。现在,将树减少为一个值是微不足道的,但以解析为代价来完成大部分工作。

代码语言:javascript
代码运行次数:0
运行
复制
# 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中寻找一些从头开始解析数学的帮助,你可以看看我的旧项目,但它是一个学生(我)写的业余代码。另一方面,不分享是不公平的,在这里你可以去:

*不一定是编程意义上的不同类型,但对我们来说肯定是不同的类型或含义。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70226987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档