cách sử dụng câu lệnh switch ()


106

Tôi hơi bối rối về câu lệnh switch trong R. Đơn giản chỉ cần truy cập hàm, tôi nhận được một ví dụ như sau:

Cách sử dụng phổ biến của switch là rẽ nhánh theo giá trị ký tự của một trong các đối số của một hàm.

 > 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

Tuy nhiên, điều này có vẻ giống như chỉ có một loạt các ifcâu lệnh được chỉ định cho mỗitype

Đó là tất cả những switch()gì cần làm ? Ai đó có thể cho tôi thêm ví dụ và các ứng dụng tốt hơn không?


10
Vâng, đó là tất cả những gì cần làm.
Andrie

Câu trả lời:


119

Vâng, thời gian để giải cứu một lần nữa. Nó có vẻ như switchlà nhanh hơn các ifcâu lệnh. Vì vậy, và thực tế là mã ngắn hơn / gọn gàng hơn với một switchcâu lệnh nghiêng về 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

Cập nhật Với nhận xét của Joshua, tôi đã thử các cách khác để đánh giá điểm chuẩn. Dấu hiệu vi mô có vẻ là tốt nhất. ... và nó hiển thị thời gian tương tự:

> 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

Cập nhật cuối cùng Đây cho thấy mức độ linh hoạt của switchnó:

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

Điều này ánh xạ case2case3đến 2.5và (không tên) mặc định thành 99. Để biết thêm thông tin, hãy thử?switch


3
Sử dụng vòng lặp for như vậy có thể gây ra sự cố với việc thu gom rác. Sự khác biệt là nhỏ hơn nhiều với một chức năng điểm chuẩn tốt hơn: benchmark(test1('trimmed'), test2('trimmed'), replications=1e6).
Joshua Ulrich

@JoshuaUlrich ... benchmarkbạn đang sử dụng chức năng nào? Có vẻ như không phải là cái rõ ràng từ gói "điểm chuẩn"?
Tommy

1
Theo stackoverflow.com/questions/6262203/…, "microbenchmark" thậm chí còn tốt hơn.
Tommy

@JoshuaUlrich - Tôi đã cập nhật câu trả lời với kết quả từ microbencmark, nhưng chúng rất giống với kết quả ban đầu của tôi. Tôi không thực sự thấy rbenchmark sẽ giải quyết vấn đề GC như thế nào, nhưng nó có vẻ tốn nhiều chi phí hơn bằng cách gọi evalreplicate.
Tommy

Tôi có thể có nhiều trường hợp với cùng một đầu ra không? tức làswitch(type, c(this,that)=do something)
LostLin

4

Trong ngắn hạn, . Nhưng đôi khi bạn có thể ủng hộ cái này so với cái kia. Google "chuyển đổi trường hợp so với nếu khác". Cũng có một số cuộc thảo luận trên SO. Ngoài ra, đây là một video hay nói về nó trong ngữ cảnh của MATLAB:

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

Cá nhân tôi, khi tôi có từ 3 trường hợp trở lên, tôi thường chỉ đi với trường hợp / công tắc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.