我想编写一个R函数arg2str
,该函数返回作为参数输入的符号的名称(字符串的向量)。
在最简单的情况下,我只有一个输入符号:
library ("rlang")
arg2str.v0 <- function (arg) rlang::quo_name (enquo (arg))
arg2str.v0 (a)
## [1] "a"
如果我有多个符号,则可以使用三点结构:
arg2str.v1 <- function (...) sapply (enquos (...), rlang::quo_name)
arg2str.v1 (a, b, c)
##
## "a" "b" "c"
(辅助问题:为什么在这种情况下,显示的字符串矢量带有初步的换行符而不是初步的[1]
?)
但是我实际上想处理符号向量。但是:
sym2str.v1 (c(a, b, c))
##
## "c(a, b, c)"
如何调整我的功能呢?
我的第一个直觉是首先通过使用sapply
来对参数向量中包含的符号进行报价(而不是对参数向量本身进行报价),然后将rlang::quo_name
应用于所得的结果向量。但是,似乎在sapply
上对其进行调用之前,在enquote
内对自变量向量中的符号进行了评估:
arg2str.v2 <- function (args) {
enquo_args <- sapply (args, enquo)
lapply (enquo_args, rlang::quo_name)
}
arg2str.v2 (c (a, b, c))
## Error in lapply(X = X, FUN = FUN, ...) : object 'a' not found
答案 0 :(得分:1)
使用substitute
和deparse
的一个可能的骇客答案:
arg2str.v3 <- function (args) {
strs <- sapply (substitute (args), deparse)
if (length (strs) > 1) { strs <- strs [-1] }
return (strs)
}
arg2str.v3 (c (a, b, c))
## [1] "a" "b" "c"
请注意,如果提供命名矢量作为输入,它也会保留名称:
arg2str.v3 (c (n1 = a, n2 = b, n3 = c))
## n1 n2 n3
## "a" "b" "c"
答案 1 :(得分:0)
我不确定您想要的内容是否有矢量化的tidyeval操作。您可以尝试
f <- function(v) {
v <- rlang::quo_name(enquo(v))
gsub('^c\\(|\\s|\\)$', '', v) %>%
strsplit(',') %>%
unlist
}
f(c(a, b, c))
#[1] "a" "b" "c"
可以与a
,c(a)
或c(a, b)
形式的输入一起使用,但是有点hacky ...
您的副问题的答案(为什么arg2str.v1(a, b, c)
不在行首打印"[1]"
)是它返回了一个命名向量,其名称为空字符串(例如,与set_names(c('a', 'b', 'c'), c('', '', ''))
的输出)。
答案 2 :(得分:0)
使用rlang约定,这应该可以工作:
return_args <- function(args){
args_expr <- enexpr(args)
if(length(args_expr) == 1) {
args_vars <- as.list(args_expr)
} else {
args_vars <- as.list(args_expr)[-1]
}
sapply(args_vars, quo_name)
}
return_args(c(a, b, c))
[1] "a" "b" "c"
return_args(a)
[1] "a"