给定一个算术表达式,例如x + y*z
,我想把它转换成add(x, multiply(y, z))
。
我发现了一个helpful function here:
> getAST <- function(ee) purrr::map_if(as.list(ee), is.call, getAST)
> getAST(quote(x + y*z))
[[1]]
`+`
[[2]]
x
[[3]]
[[3]][[1]]
`*`
[[3]][[2]]
y
[[3]][[3]]
z
字符串
可以使用rapply(result, as.character, how = "list")
来获取字符而不是符号。
如何从这个AST中得到add(x, multiply(y, z))
(结果)?当有一些括号时,这变得更加复杂:
> getAST(quote((x + y) * z))
[[1]]
`*`
[[2]]
[[2]][[1]]
`(`
[[2]][[2]]
[[2]][[2]][[1]]
`+`
[[2]][[2]][[2]]
x
[[2]][[2]][[3]]
y
[[3]]
z
型
我不要求答案必须使用getAST
函数。这只是一种可能的方法。
当然,在我的真实的用例中,表达式更长。
这里有一个解决方案(我认为)的情况下,没有括号:
getAST <- function(ee) purrr::map_if(as.list(ee), is.call, getAST)
ast <- rapply(getAST(quote(x + y*z)), as.character, how = "list")
convertAST <- function(ast) {
op <- switch(
ast[[1]],
"+" = "add",
"-" = "subtract",
"*" = "multiply",
"/" = "divide"
)
left <- ast[[2]]
right <- ast[[3]]
if(is.character(left) && is.character(right)) {
return(sprintf("%s(%s, %s)", op, left, right))
}
if(is.character(left)) {
return(sprintf("%s(%s, %s)", op, left, convertAST(right)))
}
if(is.character(right)) {
return(sprintf("%s(%s, %s)", op, convertAST(left), right))
}
return(sprintf("%s(%s, %s)", op, convertAST(left), convertAST(right)))
}
convertAST(ast)
型
3条答案
按热度按时间cngwdvgl1#
我们可以这样使用替代:
字符串
如果你想要一个字符串结果,
型
eoxn13cs2#
这可能只是因为我不太理解
rapply
,但任何时候我试图使用它,我的代码都比编写自己的递归函数更复杂。在本例中,我将递归函数放在一个瘦 Package 器中,该 Package 器允许直接输入表达式,而无需使用
quote
(如果需要)。字符串
这允许直接输入表达式:
型
或间接输入:
型
并处理任意深度的嵌套,使括号保持不变:
型
gab6jxml3#
使用外部包,这也可以用
rrapply()
(在rrapply
包中)来完成,与基本rapply()
相反,它也通过调用对象/表达式向量递归:字符串