การใช้งานคำสั่ง switch ()


106

ฉันสับสนเล็กน้อยเกี่ยวกับคำสั่ง switch ใน R เพียงแค่ googling ฟังก์ชั่นฉันได้รับตัวอย่างดังนี้:

การใช้สวิตช์ทั่วไปคือการแยกสาขาตามค่าอักขระของอาร์กิวเมนต์ตัวใดตัวหนึ่งของฟังก์ชัน

 > 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

อย่างไรก็ตามสิ่งนี้ดูเหมือนจะเหมือนกับการมีifข้อความจำนวนมากที่กำหนดไว้สำหรับแต่ละข้อtype

นั่นคือทั้งหมดที่มีเพื่อswitch()? ใครช่วยยกตัวอย่างเพิ่มเติมและแอปพลิเคชันที่ดีกว่านี้ให้ฉันได้ไหม


10
ใช่นั่นคือทั้งหมดที่มีให้
Andrie

คำตอบ:


119

ได้เวลาช่วยเหลืออีกครั้ง ดูเหมือนว่า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)

แผนที่นี้case2และcase3ไป2.5และ (ไม่มีชื่อ) 99ที่จะเริ่มต้น สำหรับข้อมูลเพิ่มเติมลอง?switch


3
การใช้ for loop แบบนี้อาจทำให้เกิดปัญหากับการรวบรวมขยะ benchmark(test1('trimmed'), test2('trimmed'), replications=1e6)ความแตกต่างที่มีขนาดเล็กมากด้วยฟังก์ชั่นที่ดีกว่าการเปรียบเทียบ:
Joshua Ulrich

@JoshuaUlrich ... benchmarkใช้ฟังก์ชันไหนคะ? ไม่ใช่สิ่งที่ชัดเจนจากแพคเกจ "เกณฑ์มาตรฐาน" ดูเหมือนว่า?
Tommy

1
อ้างอิงจากstackoverflow.com/questions/6262203/… "microbenchmark" ดียิ่งขึ้น
Tommy

@JoshuaUlrich - ฉันอัปเดตคำตอบพร้อมผลลัพธ์จากmicrobencmarkแต่มันคล้ายกับคำตอบเดิมของฉันมาก ฉันไม่เห็นว่า rbenchmark จะจัดการกับปัญหา GC ได้อย่างไร แต่ดูเหมือนว่าจะมีค่าใช้จ่ายมากกว่านี้โดยการโทรevalและreplicate.
Tommy

ฉันสามารถมีหลายกรณีที่มีเอาต์พุตเดียวกันได้หรือไม่? ieswitch(type, c(this,that)=do something)
LostLin

4

ในระยะสั้นใช่ใช่แต่มีหลายครั้งที่คุณอาจชอบคนหนึ่งกับอีกคน Google "case switch vs. if else" มีการพูดคุยเกี่ยวกับ SO ด้วยเช่นกัน นอกจากนี้นี่คือวิดีโอที่ดีที่พูดถึงเรื่องนี้ในบริบทของ MATLAB:

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

โดยส่วนตัวแล้วเมื่อฉันมี 3 เคสขึ้นไปฉันมักจะใช้เคส / สวิตช์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.