web-dev-qa-db-fra.com

Utilisation de l'instruction switch ()

Je suis un peu confus au sujet de l'instruction switch dans R. Simplement, on recherche un exemple dans Google:

Une utilisation courante de switch consiste à créer une branche en fonction de la valeur de caractère de l'un des arguments d'une fonction.

 > 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

Cependant, cela semble être la même chose que d'avoir un groupe d'instructions if désignées pour chaque type

Est-ce tout ce qu'il y a à switch()? Quelqu'un peut-il me donner d'autres exemples et de meilleures applications?

104
LostLin

Eh bien, chronométrez encore à la rescousse. Il semble que switch soit généralement plus rapide que les instructions if. Donc, et le fait que le code soit plus court/ordonné avec une instruction switch penche en faveur de 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

Mise à jour Avec le commentaire de Joshua à l'esprit, j'ai essayé d'autres méthodes de comparaison. Le micro-critère semble le meilleur. ... et il montre des timings similaires:

> 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

Mise à jour finale Voici comment la polyvalence de switch est:

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

Cela mappe case2 et case3 à 2.5 et la valeur par défaut (non nommée) à 99. Pour plus d'informations, essayez ?switch

113
Tommy

En bref, oui . Mais il y a des moments où vous pourriez favoriser l'un par rapport à l'autre. Google "changement de casse vs. if else". Il y a déjà quelques discussions sur SO. En outre, voici une bonne vidéo qui en parle dans le contexte de MATLAB:

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

Personnellement, quand j'ai 3 cas ou plus, je vais généralement juste avec cas/commutateur.

4
John Colby