【问题标题】:switch() statement usageswitch() 语句用法
【发布时间】:2011-12-11 03:34:23
【问题描述】:

我对 R 中的 switch 语句有点困惑。 简单地用谷歌搜索我得到一个例子如下:

switch 的一个常见用途是根据函数参数之一的字符值进行分支。

 > centre <- function(x, type) {
 + switch(type,
 +        mean = mean(x),
 +        median = median(x),
 +        trimmed = mean(x, trim = .1))
 + }
 > x <- rcauchy(10)
 > centre(x, "mean")
 [1] 0.8760325
 > centre(x, "median")
 [1] 0.5360891
 > centre(x, "trimmed")
 [1] 0.6086504

但这似乎与为每个 type 指定一堆 if 语句相同

这就是switch() 的全部内容吗?谁能给我更多的例子和更好的应用?

【问题讨论】:

  • 是的,就是这样。

标签: r switch-statement


【解决方案1】:

好吧,又到了救援的时机。似乎switch 通常比if 语句快。 因此,使用switch 语句的代码更短/更整洁的事实倾向于switch

# Simplified to only measure the overhead of switch vs if

test1 <- function(type) {
 switch(type,
        mean = 1,
        median = 2,
        trimmed = 3)
}

test2 <- function(type) {
 if (type == "mean") 1
 else if (type == "median") 2
 else if (type == "trimmed") 3
}

system.time( for(i in 1:1e6) test1('mean') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('mean') ) # 1.13 secs
system.time( for(i in 1:1e6) test1('trimmed') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('trimmed') ) # 2.28 secs

更新 考虑到 Joshua 的评论,我尝试了其他方法来进行基准测试。微基准似乎是最好的。 ...它显示了类似的时间:

> library(microbenchmark)
> microbenchmark(test1('mean'), test2('mean'), times=1e6)
Unit: nanoseconds
           expr  min   lq median   uq      max
1 test1("mean")  709  771    864  951 16122411
2 test2("mean") 1007 1073   1147 1223  8012202

> microbenchmark(test1('trimmed'), test2('trimmed'), times=1e6)
Unit: nanoseconds
              expr  min   lq median   uq      max
1 test1("trimmed")  733  792    843  944 60440833
2 test2("trimmed") 2022 2133   2203 2309 60814430

最终更新这里展示了switch 的多功能性:

switch(type, case1=1, case2=, case3=2.5, 99)

这会将case2case3 映射到2.5,并且(未命名的)默认值映射到99。欲了解更多信息,请尝试?switch

【讨论】:

  • 使用这样的 for 循环可能会导致垃圾收集问题。使用更好的基准测试功能,差异要小得多:benchmark(test1('trimmed'), test2('trimmed'), replications=1e6)
  • @JoshuaUlrich ...您使用的是哪个benchmark 函数?看起来不是“基准”包中明显的那个吗?
  • 根据stackoverflow.com/questions/6262203/… "microbenchmark" 是一个更好的。
  • @JoshuaUlrich - 我用microbencmark 的结果更新了答案,但它们与我原来的结果非常相似。我真的不知道 rbenchmark 如何解决 GC 问题,但调用 evalreplicate 似乎有更多开销。
  • 顺便说一句,我可以有多个具有相同输出的案例吗?即switch(type, c(this,that)=do something)
【解决方案2】:

简而言之,是的。但有时您可能会偏爱一个与另一个。谷歌“case switch vs. if else”。也有一些关于 SO 的讨论。另外,这是一个在 MATLAB 的上下文中讨论它的好视频:

http://blogs.mathworks.com/pick/2008/01/02/matlab-basics-switch-case-vs-if-elseif/

就我个人而言,当我有 3 个或更多 case 时,我通常只使用 case/switch。

【讨论】:

    【解决方案3】:

    Switch 也比一系列 if() 语句更容易阅读。怎么样:

    switch(id,
       "edit" = {
          CODEBLOCK
       },
       "delete" = {
          CODEBLOCK
       },
       stop(paste0("No handler for ", id))
     )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多