当我已经在使用省略号时,如何将其他参数传递给 FUN?

  • 本文关键字:其他 参数传递 FUN 省略号 r
  • 更新时间 :
  • 英文 :


>我有一个这样的函数来检索项目。

fetchItem <- function(name, ..., FUN)
  • 名称:文件名的字符串
  • ...:路径或URL等的零到许多部分,它在幕后构建了完整的路径(无需过多详细介绍,这对于消费者来说非常重要,他们可以向它扔任何东西,它只是"为他们做这一切"(
  • FUN:[可选]为您想要如何读取它定义一个"读取器"函数(JSON 与 CSV 等的不同读取器函数处理并按照他们想要的方式返回它(。

到目前为止一切顺利,效果很好。但是现在我有一个请求,他们希望能够将其他参数传递给 FUN 阅读器(基本上是选项,例如它是否有标题行,如果它使用某种时髦的分隔符之类的东西,有一堆他们想要支持(。如果我能弄清楚如何通过它传递它们,读者将能够处理这些额外的参数,但我是 R 的新手,并且正在努力解决它如何链接在一起的语法。

为了说明我上面最后一条评论中的观点,这样的事情怎么样?

do_something <- function(x, ..., FUN = NULL) {
if (is.null(FUN)) print(x)
# Get all additional arguments
args <- list(...)
# Match additional arguments that are allowed for FUN
args_for_FUN <- NULL
if (length(args) > 0) {
allowed_args_for_FUN = c("na.rm")
# Allow for partial matching
names(args) <- sapply(names(args), function(arg)
match.arg(arg, allowed_args_for_FUN))
args_for_FUN <- args[names(args) %in% allowed_args_for_FUN]
}
# Execute FUN (if given)
if (is.function(FUN)) do.call(FUN, c(list(x = x), args_for_FUN))
}

让我们做一些测试用例:

# Case 1: No FUN, no additional args
do_something(1:10)
# [1]  1  2  3  4  5  6  7  8  9 10
# Case 2: With FUN, no additional args
do_something(1:10, FUN = mean)
#[1] 5.5
# Case 3: With FUN, no additional args
do_something(c(1:10, NA), FUN = mean)
#[1] NA
# Case 4: With FUN, with an additional arg for FUN
do_something(c(1:10, NA), na.rm = T, FUN = mean)
#[1] 5.5

虽然我可以想象有时这可能是有问题的,但一种技术可能是将所有未命名的参数用于一个目的,并要求所有FUN参数都显式命名。

过度简化您对...的使用只是连接到文件路径:

fetchItem <- function(name, ..., FUN) {
dots <- list(...)
nms <- names(dots)
args1 <- is.null(nms) | nms == ""
list(
nofunargs = c(name = name, dots[args1]),
funargs = dots[!args1]
)
}
str( fetchItem("foo", "bar", FUN = read.csv, stringsAsFactors = FALSE, header = TRUE) )
# List of 2
#  $ nofunargs:List of 2
#   ..$ name: chr "foo"
#   ..$     : chr "bar"
#  $ funargs  :List of 2
#   ..$ stringsAsFactors: logi FALSE
#   ..$ header          : logi TRUE

另一种选择有点脆弱:FUN=(必须命名(之后的参数被传递给FUN,而不是第一个目的。

fetchItem2 <- function(name, ..., FUN) {
args <- as.list(sys.call())[-1]
nms <- names(args)
FUNind <- which(nms == "FUN")
if (!length(FUNind)) FUNind <- length(nms) + 1L
list(
nofunargs = args[ seq_len(FUNind - 1L) ],
funargs = args[ -seq_len(FUNind) ]
)  
}
str( fetchItem2("foo", "bar", FUN = read.csv, stringsAsFactors = FALSE, header = TRUE, name = "othername") )
# List of 2
#  $ nofunargs:List of 2
#   ..$ : chr "foo"
#   ..$ : chr "bar"
#  $ funargs  :List of 3
#   ..$ stringsAsFactors: logi FALSE
#   ..$ header          : logi TRUE
#   ..$ name            : chr "othername"

最新更新