问题 使用switch命令中的可能值列表


是否有可能为我提供一种可能的值列表 switch 功能。如果有人提供了错误的参数,我很乐意让所有内容自动更新。

我用 {} 对于每个条件,因为我将在我的函数中执行更多然后只是这个变量声明,我会在这个开关中做几件事。

switch(con,
       val1={
         filename <- 'SILAC-DML_with_PDF.R'
       },
       val2={
         filename <- 'SILAC-DML_with_PDF.R'
       },
       stop(sprintf('"%s" is an unknown condition type, please use one of "%s".\n',
                    con, paste(c('val1','val2'), collapse=', '))))

我希望有一个列表,我可以粘贴名称,以获得可能的值。所以理想的解决方案有点像这样,但没有错误信息:-)

my_list <- list(val1=filename <- 'a.R',
                val2=filename <- 'b.R')
switch(con,
       my_list,
       stop(sprintf('"%s" is an unknown condition type, please use one of "%s".\n',
                    con, names(my_list), collapse=', '))))

2278
2017-07-21 11:53


起源



答案:


switch 函数是多余的,您可以直接对值列表进行子集化:

alternatives = list(val1 = 'SILAC-DML_with_PDF.R',
                    val2 = 'SILAC-DML_with_PDF.R')
result = alternatives[[con]]
if (is.null(result))
    stop(…)

... switch 在R中是一个奇怪的野兽。我从来没有真正发现它有用。

如果您需要执行更复杂的操作,请考虑使用函数列表:

alternatives = list(
    val1 = function () { message('foo') },
    val2 = function () { message('bar') }
)

if (! con %in% names(alternatives))
    stop(…)
result = alternatives[[con]]()

我不认为这可以通过巧妙实现 switch 但它当然可以包含在它自己的小功能中。请注意,与Hadley的答案不同,以上所有内容都避免了部分参数名称匹配,这是一个巨大的错误来源,并且属于从地球上消失的。


11
2017-07-21 11:59



目前我只是在其中一个条件中定义一个变量,但是稍后在脚本中我将在交换机中做更多的事情,或者这至少是我的计划:-)这就是为什么我使用这个奇怪的结构,但你的解决方案也很有趣。 - drmariod
@drmariod啊,有效评论。在那种情况下,我建议使用函数列表和子集。 - Konrad Rudolph
所以只需调用列表中的函数?!嗯,听起来像我正在寻找的解决方案......我稍微更新了我的问题。 - drmariod
@drmariod好的,我也更新了我的答案。 - Konrad Rudolph
我觉得这很完美。不再用于开关了!之前没有考虑过这些匿名函数。完善。您可以重新排列答案并将列表/功能解决方案放在顶部。 :-) 谢谢 - drmariod


答案:


switch 函数是多余的,您可以直接对值列表进行子集化:

alternatives = list(val1 = 'SILAC-DML_with_PDF.R',
                    val2 = 'SILAC-DML_with_PDF.R')
result = alternatives[[con]]
if (is.null(result))
    stop(…)

... switch 在R中是一个奇怪的野兽。我从来没有真正发现它有用。

如果您需要执行更复杂的操作,请考虑使用函数列表:

alternatives = list(
    val1 = function () { message('foo') },
    val2 = function () { message('bar') }
)

if (! con %in% names(alternatives))
    stop(…)
result = alternatives[[con]]()

我不认为这可以通过巧妙实现 switch 但它当然可以包含在它自己的小功能中。请注意,与Hadley的答案不同,以上所有内容都避免了部分参数名称匹配,这是一个巨大的错误来源,并且属于从地球上消失的。


11
2017-07-21 11:59



目前我只是在其中一个条件中定义一个变量,但是稍后在脚本中我将在交换机中做更多的事情,或者这至少是我的计划:-)这就是为什么我使用这个奇怪的结构,但你的解决方案也很有趣。 - drmariod
@drmariod啊,有效评论。在那种情况下,我建议使用函数列表和子集。 - Konrad Rudolph
所以只需调用列表中的函数?!嗯,听起来像我正在寻找的解决方案......我稍微更新了我的问题。 - drmariod
@drmariod好的,我也更新了我的答案。 - Konrad Rudolph
我觉得这很完美。不再用于开关了!之前没有考虑过这些匿名函数。完善。您可以重新排列答案并将列表/功能解决方案放在顶部。 :-) 谢谢 - drmariod


你可以使用而不是开关 match.arg() 和子集:

filenames <- c(
  val1 = "a.R",
  val2 = "b.R"
)
con <- match.arg(con, names(filenames))

filename <- filenames[[con]]

请注意,这允许部分匹配 con,对您的用例可能有用也可能没有帮助。


3
2017-07-21 12:01



我稍微更新了一下我的问题。文件名的东西只是一个占位符,我会在开关中做更多的命令。 - drmariod
呃,@哈德利的第一个回答......我感到很荣幸:-) - drmariod