如何将列表元素作为参数传入CDM::IRT.compareModels及R可变参数函数
如何将列表元素作为多参数传入R函数(以CDM::IRT.compareModels为例)
问题背景
当函数签名为the_function(arg1, ...)时,合法调用是the_function(1, 2, 3, 4, 5)这类多参数形式,但如果参数都存储在列表(比如my_list <- list(1, 2, 3, 4, 5))中,直接用my_list |> the_function()会被解析成the_function(arg1 = my_list)——把整个列表当成了第一个参数,无法实现逐个传参的需求。
放到CDM::IRT.compareModels的场景里:官方示例是直接传入多个模型对象,但如果模型预先存在列表中,直接用管道传递列表会导致参数解析错误。
解决方法
在R中,要把列表元素展开为多个位置参数传入函数,常用两种方法:
方法1:使用do.call()(兼容所有R版本)
do.call()的核心作用就是将列表中的元素拆解为独立参数传递给目标函数,语法为do.call(函数名, 参数列表)。
针对CDM::IRT.compareModels的完整示例:
data(sim.dina, package="CDM") data(sim.qmatrix, package="CDM") dat <- sim.dina q.matrix <- sim.qmatrix # 构建模型 mod0 <- CDM::din(dat, q.matrix, guess.equal=TRUE, slip.equal=TRUE) mod1 <- CDM::din(dat, q.matrix) # 将模型存入列表 my_model_list <- list(mod0, mod1) # 正确调用方式 do.call(CDM::IRT.compareModels, my_model_list) # 结合管道的写法 my_model_list |> do.call(what = CDM::IRT.compareModels)
方法2:使用R 4.1+的!!!运算符(管道风格)
如果偏好管道写法,可以结合匿名函数和!!!运算符(用于展开列表元素):
my_model_list |> { \(x) CDM::IRT.compareModels(!!!x) }()
这里的!!!x会把列表x中的每个模型对象拆解为独立的位置参数,传递给IRT.compareModels。
原写法失效原因
my_list |> IRT.compareModels()等价于IRT.compareModels(my_list),即把整个列表作为单个参数传给函数,而IRT.compareModels需要的是多个模型对象作为独立的位置参数,因此必须通过上述方法展开列表元素。
内容的提问来源于stack exchange,提问作者user1
相关产品推荐
相关产品推荐

