我想将R表达式解析为列表,并可选择在最终将其转换为json对象之前修改它的各个方面。举个例子,我想尝试类似的东西:
{"op": "=",
"content": {
"lhs": "gender",
"rhs": ["male"]
}
}
我将从R表达式开始,如:
gender == "male"
我可以使用pryr::ast
来获取树的文本版本,但我希望将其作为列表:
op: "=="
[[1]]: "gender"
[[2]]: "male"
列表的“格式”的细节并不那么重要,只是为了清楚。我只是想获得一个可计算且可修改的R表达式的解析树。
答案 0 :(得分:4)
这就是你想要的东西吗?
expr <- quote(gender == "male")
expr[[1]]
# `==`
expr[[2]]
# gender
expr[[3]]
# "male"
expr[[3]] <- "female"
expr
# gender == "female"
答案 1 :(得分:2)
以下是您的请求的输出部分的方法,使用我的评论中引用的方法的修改。这是基于哈德利的pkg:pryr。有关中缀运算符的列表,请参阅?Ops
。我已经看到函数lhs
和rhs
在Hadley的高级编程文本中定义了... IIRC。显然,唯一被标记为&#39; ops&#39;将是中缀数学和逻辑,但可以使用?groupGeneric
页面中的其他列表完成Math(),Complex()和Summary()函数的更完整标记:
call_tree2(quote(gender == "male")) # relabeling of items in pryr-functions
#--------
- call:
- `op: ==
- `gender
- "male"
下面定义的函数:
library(pryr) # also loads the stringr namespace
# although the `tree` function is not exported, you can see it with:
pryr:::tree # now for some hacking and adding of logic
tree2<-
function (x, level = 1, width = getOption("width"), branch = " - ")
{
indent <- str_c(str_dup(" ", level - 1), branch)
if (is.atomic(x) && length(x) == 1) {
label <- paste0(" ", deparse(x)[1])
children <- NULL
}
else if (is.name(x)) {
x <- as.character(x)
if (x == "") {
label <- "`MISSING"
}
if (x %in% c("+", "-", "*", "/", "^", "%%", "%/%",
"&", "|", "!","==", "!=", "<", "<=", ">=", ">") ) {
label <- paste0("`op: ", as.character(x))}
else {
label <- paste0("`", as.character(x))
}
children <- NULL
}
else if (is.call(x)) {
label <- "call:"
children <- vapply(as.list(x), tree2, character(1), level = level +
1, width = width - 3)
}
else if (is.pairlist(x)) {
label <- "[]"
branches <- paste("", format(names(x)), "=")
children <- character(length(x))
for (i in seq_along(x)) {
children[i] <- tree2(x[[i]], level = level + 1, width = width -
3, branch = branches[i])
}
}
else {
if (inherits(x, "srcref")) {
label <- "<srcref>"
}
else {
label <- paste0("", typeof(x), "")
}
children <- NULL
}
label <- str_trunc(label, width - 3)
if (is.null(children)) {
paste0(indent, label)
}
else {
paste0(indent, label, "\n", paste0(children, collapse = "\n"))
}
}
environment(tree2)<-environment(pryr:::tree)
现在用call_tree2调用它:
pryr::call_tree
call_tree2 <-
function (x, width = getOption("width"))
{
if (is.expression(x) || is.list(x)) {
trees <- vapply(x, tree2, character(1), width = width)
out <- str_c(trees, collapse = "\n\n")
}
else {
out <- tree2(x, width = width)
}
cat(out, "\n")
}
environment(call_tree2)<-environment(pryr::call_tree)