将字符串作为参数名称/值对传递到R函数中

时间:2018-01-22 10:54:50

标签: r functional-programming

我想使用一个字符串,以便将它作为参数的名称/值对传递给函数。 Test1显示了我想要实现的目标。在Test2中,R不调用getInfo(PHONE_NUMBER = 123456),但是,根据参数顺序,使用getInfo(FULL_NAME =“PHONE_NUMBER = 123456”)。我怎么能改变它?

该字符串还可能包含我想要解析的各种参数,例如“PHONE_NUMBER = 123456,ZIP = 1234”


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)
}
# Test 1: Setting the paramter manually
getInfo(PHONE_NUMBER = 123456)
#> [1] "PHONE_NUMBER" "PHONE_NUMBER"
#> PHONE_NUMBER PHONE_NUMBER 
#>       123456       123456
# Test2 : Attempt to pass string as name/value fails; R uses the complete string as the first paramter (FULL_NAME = "PHONE_NUMBER = 123456") instead
getInfo(s)
#> [1] "FULL_NAME" "FULL_NAME"
#> $FULL_NAME
#> s
#> 
#> $FULL_NAME
#> s

2 个答案:

答案 0 :(得分:1)

我们可以创建一个环境并在环境中创建变量。然后将环境转换为列表,并将变量列表作为参数传递给函数。

要了解有关R中环境的更多信息,请参阅此link

没有字符串s

getInfo(PHONE_NUMBER = 123456)
do.call("getInfo", list(PHONE_NUMBER = 123456))
# [1] "PHONE_NUMBER" "PHONE_NUMBER"
# PHONE_NUMBER PHONE_NUMBER 
# 123456       123456

字符串s包含单个参数

s <- "PHONE_NUMBER = 123456"
myenv <- new.env()  # create new environment
eval(parse(text = s), envir = myenv)  # create variables inside environment using string s
ls(name = myenv)  # list all variables inside the environment
# [1] "PHONE_NUMBER"
myenv$PHONE_NUMBER
# [1] 123456
do.call("getInfo", as.list.environment(myenv))  # call the function by passing the arguments which is obtained by converting environment into list
# [1] "PHONE_NUMBER" "PHONE_NUMBER"
# PHONE_NUMBER PHONE_NUMBER 
# 123456       123456 

字符串s包含多个参数 - 适用于单个或多个参数

s <- "PHONE_NUMBER = 123456, ZIP = 1234"
s <- unlist(strsplit(s, split = ",", fixed = TRUE))  # split string s using comma separator
s
# [1] "PHONE_NUMBER = 123456" " ZIP = 1234" 
myenv <- new.env()
eval(parse(text = s), envir = myenv)
ls(name = myenv)
# [1] "PHONE_NUMBER" "ZIP" 
do.call("getInfo", as.list.environment(myenv))
# [1] "ZIP"          "PHONE_NUMBER"
# ZIP PHONE_NUMBER 
# 1234       123456 

答案 1 :(得分:0)

上面的

@Sathish回答很好,但不适用于更复杂的参数。 例如,当要传递矢量(包含逗号)时:

> s <- "PHONE_NUMBER = 123456, ZIP = c(1234, 4321)"
> s <- unlist(strsplit(s, split = ",", fixed = TRUE))
> myenv <- new.env()
> eval(parse(text = s), envir = myenv)
Error in parse(text = s) : <text>:3:2: unexpected numeric constant
2:  ZIP = c(1234
3:  4321

有一种更好,更灵活的方法,使用R的机器来达到目的:

> s <- "PHONE_NUMBER = 123456, ZIP = c(1234, 4321)"
> getArgs <- function(...) return(list(...))
> pars <- try(eval(parse(text=sprintf("getArgs(%s)", s))), silent=TRUE)
> pars
$PHONE_NUMBER
[1] 123456

$ZIP
[1] 1234 4321

即使s在语法上不正确,它也可以工作-在这种情况下,pars将包含类"try-error"的对象。

尽管如此,使用eval()仍存在重要的安全风险。为了避免不愉快的意外(=用户执行任意代码),您可能希望禁止并删除任何“;”或s中的换行符:

s <- gsub(";|\n", "", s)