switch () deyimi kullanımı


106

R'deki switch deyimi hakkında biraz kafam karıştı. Basitçe işlevi googling yaparken aşağıdaki gibi bir örnek alıyorum:

Anahtarın yaygın bir kullanımı, bağımsız değişkenlerden birinin karakter değerine göre bir işleve ayrılmaktır.

 > 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

Ancak bu if, her biri için belirlenmiş bir grup ifadeye sahip olmakla aynı gibi görünüyor.type

Tüm olan bu switch()mu? Birisi bana daha fazla örnek ve daha iyi uygulamalar verebilir mi?


10
Evet, hepsi bu kadar.
Andrie

Yanıtlar:


119

Yine kurtarma zamanı. Görünüşe switchgöre genellikle ififadelerden daha hızlıdır . Öyleyse, bir switchifadeyle kodun daha kısa / daha düzgün olması şunların lehine olur 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

Güncelleme Joshua'nın yorumunu göz önünde bulundurarak, kıyaslama yapmak için başka yollar denedim. Mikro ölçüt en iyi görünüyor. ... ve benzer zamanlamaları gösteriyor:

> 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

Son Güncelleme İşte ne kadar çok yönlü switcholduğunu gösteriyor :

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

Bu, case2ve case3to 2.5ve (adsız) varsayılan olarak eşleşir 99. Daha fazla bilgi için deneyin?switch


3
Bunun gibi bir for döngüsü kullanmak, çöp toplamayla ilgili sorunlara neden olabilir. Fark daha iyi kıyaslama fonksiyonu ile çok daha küçük: benchmark(test1('trimmed'), test2('trimmed'), replications=1e6).
Joshua Ulrich

@JoshuaUlrich ... hangi benchmarkişlevi kullanıyorsunuz? Görünüşe göre "benchmark" paketinden aşikar olan değil mi?
Tommy

1
Stackoverflow.com/questions/6262203/… 'e göre "microbenchmark" daha da iyi.
Tommy

@JoshuaUlrich - Yanıtı sonuçlarıyla güncelledim microbencmark, ancak orijinallerime çok benziyorlar. Rbenchmark'ın GC sorununu nasıl aşacağını gerçekten anlamıyorum, ancak evalve replicate.
Tommy

aynen aynı çıktıya sahip birden fazla davam olabilir mi? yaniswitch(type, c(this,that)=do something)
LostLin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.