如何将字符串格式的参数名值对传入R函数?
如何将字符串形式的名值对传入R函数作为参数?
你遇到的这个问题很典型——直接传字符串的话,R会把整个字符串当成第一个位置参数的值,不会自动解析里面的key=value格式。下面我结合你的代码示例,给你两种解决思路,不管是单个参数还是多个参数的情况都能适用:
首先先回顾下你的代码场景:
s <- "PHONE_NUMBER = 123456" getInfo <- function(FULL_NAME = "", FIRST_NAME = "", LAST_NAME = "", ZIP = "", PHONE_NUMBER = "") { l <- as.list(match.call()) myNames <- names(unlist(l[c(2, length(l))])) print(myNames) myValues <- unlist(l[c(2, length(l))]) print(myValues) searchString <- paste(myNames, myValues, sep = "=", collapse = "&") searchString <- paste0("search?PHONE_NUMBER=", searchString) } # 手动传参正常工作 getInfo(PHONE_NUMBER = 123456) #> [1] "PHONE_NUMBER" "PHONE_NUMBER" #> PHONE_NUMBER PHONE_NUMBER #> 123456 123456 # 直接传字符串失败,被当成FULL_NAME的参数 getInfo(s) #> [1] "FULL_NAME" "FULL_NAME" #> $FULL_NAME #> s #> #> $FULL_NAME #> "PHONE_NUMBER = 123456"
方法一:用parse() + eval()模拟手动调用
这种方法最直观,相当于把字符串拼接成完整的函数调用代码,然后用parse()解析成表达式,再用eval()执行它:
# 单个参数的情况 s <- "PHONE_NUMBER = 123456" eval(parse(text = paste0("getInfo(", s, ")"))) # 多个参数的情况,比如包含ZIP的字符串 s_multi <- "PHONE_NUMBER = 123456, ZIP = 1234" eval(parse(text = paste0("getInfo(", s_multi, ")")))
执行后就和你手动写getInfo(PHONE_NUMBER = 123456)或者getInfo(PHONE_NUMBER = 123456, ZIP = 1234)的效果完全一样,R会正确识别每个参数名和对应的值。
方法二:解析字符串成参数列表,用do.call()调用函数
如果觉得eval(parse())的方式不够安全(毕竟是执行字符串代码),可以先把字符串解析成键值对列表,再用do.call()来调用函数,这种方式更可控:
# 先写一个解析字符串的辅助函数 parse_args <- function(arg_str) { # 把字符串按逗号分割成单个键值对 arg_pairs <- strsplit(arg_str, ",\\s*")[[1]] # 逐个处理每个键值对 parsed_list <- lapply(arg_pairs, function(pair) { # 分割键和值,处理两边的空格 parts <- strsplit(pair, "\\s*=\\s*")[[1]] # 把值转换成对应类型(这里简单处理数字,你可以根据需求加更多判断) arg_value <- ifelse(grepl("^\\d+$", parts[2]), as.numeric(parts[2]), parts[2]) # 给列表元素命名,对应参数名 setNames(list(arg_value), parts[1]) }) # 合并成一个完整的参数列表 do.call(c, parsed_list) } # 单个参数测试 s <- "PHONE_NUMBER = 123456" args <- parse_args(s) do.call(getInfo, args) # 多个参数测试 s_multi <- "PHONE_NUMBER = 123456, ZIP = 1234" args_multi <- parse_args(s_multi) do.call(getInfo, args_multi)
这种方法的好处是你可以在解析过程中对参数做校验、类型转换等操作,比如如果参数值是字符串类型(比如名字),可以调整判断逻辑来处理。
额外小建议:优化你的getInfo函数
你的getInfo里用l[c(2, length(l))]来取参数,当只传一个参数的时候会重复取同一个值(比如Test1里输出了两次PHONE_NUMBER)。如果你的目的是获取所有传入的参数,可以改成l[-1](去掉列表里的第一个元素,也就是函数名本身),同时生成search字符串的部分也可以优化下,避免重复加PHONE_NUMBER=:
getInfo <- function(FULL_NAME = "", FIRST_NAME = "", LAST_NAME = "", ZIP = "", PHONE_NUMBER = "") { l <- as.list(match.call())[-1] # 只保留传入的参数,去掉函数名 myNames <- names(l) print(myNames) myValues <- unlist(l) print(myValues) searchString <- paste(myNames, myValues, sep = "=", collapse = "&") searchString <- paste0("search?", searchString) # 这里去掉了多余的PHONE_NUMBER= return(searchString) # 返回结果方便查看 }
这样修改后,不管传几个参数,都能正确生成对应的搜索字符串啦。
内容的提问来源于stack exchange,提问作者Oliver
相关产品推荐
相关产品推荐

