在R语言中如何匹配函数参数的多种组合场景?
多参数组合匹配的可扩展实现方案
问题1:n×n二维参数组合的匹配方案
完全存在可扩展到任意n×n组合的实现方案,核心思路是用嵌套命名列表作为二维查找表,直接映射参数组合和对应执行逻辑,完全不需要堆叠if判断或者嵌套switch语句。
实现步骤
- 预定义二维映射表,第一层键为
what_to_do的取值,第二层键为scenario的取值,值为对应要执行的匿名函数:
# 二维参数组合映射表 proc_map <- list( mean = list( A = function(x) mean(x, na.rm = FALSE), B = function(x) mean(x, na.rm = TRUE), C = function(x) weighted.mean(x, w = rep(1, length(x))) ), log = list( A = function(x) log(x), B = function(x) log10(x) ), median = list( A = function(x) median(x, na.rm = FALSE), B = function(x) median(x, na.rm = TRUE) ), square = list( A = function(x) x^2, B = function(x) x*x ), unique = list( A = function(x) unique(x, incomparables = FALSE), B = function(x) unique(x, incomparables = NA) ) )
- 重构
choose_procedure函数,直接按参数从映射表中取出函数执行:
choose_procedure <- function(x, what_to_do, scenario) { # 基础参数合法性校验 if (!what_to_do %in% names(proc_map)) stop("无效的what_to_do取值") if (!scenario %in% names(proc_map[[what_to_do]])) stop("无效的scenario取值") # 执行对应逻辑 proc_map[[what_to_do]][[scenario]](x) }
调用测试
# 自然对数(log场景A) choose_procedure(mtcars$mpg, "log", "A") # 以10为底的对数(log场景B) choose_procedure(mtcars$mpg, "log", "B")
后续新增参数组合只需要在proc_map中新增对应键值对即可,无需修改函数核心逻辑,哪怕是10×10的组合规模,代码也不会出现嵌套膨胀的问题。
问题2:扩展到高于二维的场景
完全可以实现更高维度的参数匹配,只需要对应加深映射表的嵌套层级即可,例如新增sub_scenario参数的三维场景:
三维映射表示例
# 三维参数组合映射表,新增sub_scenario维度 proc_map_3d <- list( mean = list( A = list( S1 = function(x) mean(x, na.rm = FALSE), S2 = function(x) mean(x, na.rm = TRUE) ), B = list( S1 = function(x) weighted.mean(x, w = rep(1, length(x))), S2 = function(x) weighted.mean(x, w = seq_along(x)) ) ) )
通用多维度适配方案
如果需要支持任意数量的匹配维度,可以借助purrr::pluck实现动态取值,不用硬写多层索引:
library(purrr) choose_procedure_general <- function(x, ..., map) { # 把所有匹配参数整理为键列表 keys <- list(...) # 动态取出对应执行函数,不存在则报错 exec_fun <- pluck(map, !!!keys, .default = stop("当前参数组合无对应实现")) exec_fun(x) }
多维度调用测试
# 二维调用 choose_procedure_general(mtcars$mpg, "log", "A", map = proc_map) # 三维调用 choose_procedure_general(mtcars$mpg, "mean", "A", "S1", map = proc_map_3d)
这种方案的可扩展性极强,不管后续新增多少个匹配维度,都不需要修改函数核心逻辑,只需要维护对应的映射表即可。
内容的提问来源于stack exchange,提问作者Emman
相关产品推荐
相关产品推荐

