switch () penggunaan pernyataan

106

Saya sedikit bingung tentang pernyataan switch di R. Cukup googling fungsinya saya mendapatkan contoh sebagai berikut:

Penggunaan umum dari sakelar adalah untuk bercabang sesuai dengan nilai karakter dari salah satu argumen ke suatu fungsi.

 > 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

Namun ini sepertinya sama dengan hanya memiliki sekumpulan ifpernyataan yang ditujukan untuk masing-masingtype

Apakah hanya itu yang bisa dilakukan switch()? Bisakah seseorang memberi saya contoh lebih lanjut dan aplikasi yang lebih baik?

LostLin
sumber
10
Ya, itu saja.
Andrie

Jawaban:

119

Nah, waktu untuk menyelamatkannya lagi. Tampaknya switchsecara umum lebih cepat daripada ifpernyataan. Sehingga, dan fakta bahwa kodenya lebih pendek / rapi dengan switchpernyataan bersandar pada 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

Perbarui Dengan mengingat komentar Joshua, saya mencoba cara lain untuk melakukan benchmark. Microbenchmark sepertinya yang terbaik. ... dan itu menunjukkan pengaturan waktu yang serupa:

> 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

Pembaruan Terakhir Berikut ini menunjukkan betapa serbaguna switch:

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

Ini memetakan case2dan case3ke 2.5dan (tanpa nama) default ke 99. Untuk informasi lebih lanjut, coba?switch

Tommy
sumber
3
Menggunakan perulangan for seperti itu dapat menyebabkan masalah dengan pengumpulan sampah. Perbedaannya adalah jauh lebih kecil dengan fungsi pembandingan yang lebih baik: benchmark(test1('trimmed'), test2('trimmed'), replications=1e6).
Joshua Ulrich
@JoshuaUlrich ... benchmarkfungsi apa yang Anda gunakan? Bukan yang jelas dari paket "patokan" sepertinya?
Tommy
1
Menurut stackoverflow.com/questions/6262203/… "microbenchmark" bahkan lebih baik.
Tommy
@JoshuaUlrich - Saya memperbarui jawaban dengan hasil dari microbencmark, tetapi hasilnya sangat mirip dengan yang asli. Saya tidak benar-benar melihat bagaimana rbenchmark akan mengatasi masalah GC, tetapi tampaknya memiliki lebih banyak overhead dengan menelepon evaldan replicate.
Tommy
sama seperti di samping dapatkah saya memiliki beberapa casing dengan output yang sama? yaituswitch(type, c(this,that)=do something)
LostLin
4

Singkatnya, ya . Tetapi ada kalanya Anda mungkin menyukai yang satu vs. yang lain. Google "case switch vs. if else". Ada beberapa diskusi sudah di SO juga. Juga, berikut adalah video bagus yang membahasnya dalam konteks MATLAB:

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

Secara pribadi, ketika saya memiliki 3 case atau lebih, saya biasanya hanya menggunakan case / switch.

John Colby
sumber