Jak używać instrukcji switch w funkcjach języka R?

81

Chciałbym użyć dla mojej funkcji w R instrukcji, switch()aby wyzwolić różne obliczenia w zależności od wartości argumentu funkcji.

Na przykład w Matlabie możesz to zrobić pisząc

switch(AA)        
case '1'   
...   
case '2'   
...   
case '3'  
...  
end

Znalazłem to post - użycie instrukcji switch () - które wyjaśniają, jak używać switch, ale nie są dla mnie pomocne, ponieważ chcę wykonywać bardziej wyrafinowane obliczenia (operacje na macierzach), a nie proste mean.

Szymon
źródło

Odpowiedzi:

112

Cóż, switchprawdopodobnie tak naprawdę nie było przeznaczone do pracy w ten sposób, ale możesz:

AA = 'foo'
switch(AA, 
foo={
  # case 'foo' here...
  print('foo')
},
bar={
  # case 'bar' here...
  print('bar')    
},
{
   print('default')
}
)

... każdy przypadek jest wyrażeniem - zwykle jest to po prostu prosta rzecz, ale tutaj używam kręconego bloku, abyś mógł włożyć tam dowolny kod, który chcesz ...

Tommy
źródło
6
czy istnieje sposób na zrobienie tego bez porównywania ze stringami? wydaje się to bardzo nieefektywne.
Jules GM
10
Jako nowy użytkownik switch(), zastanawiam się, dlaczego mówisz, że nie ma tak działać. Czego jeszcze można by się spodziewać po instrukcji switch?
eric_kernfeld
46

te różne sposoby przełączania ...

# by index
switch(1, "one", "two")
## [1] "one"


# by index with complex expressions
switch(2, {"one"}, {"two"})
## [1] "two"


# by index with complex named expression
switch(1, foo={"one"}, bar={"two"})
## [1] "one"


# by name with complex named expression
switch("bar", foo={"one"}, bar={"two"})
## [1] "two"
petermeissner
źródło
42

Mam nadzieję, że ten przykład pomoże. Możesz użyć nawiasów klamrowych, aby upewnić się, że masz wszystko zawarte w kolesiu zmieniacza przełączników (przepraszam, nie znam terminu technicznego, ale termin poprzedzający znak =, który zmienia to, co się dzieje). Myślę o przełączniku jako o bardziej kontrolowanej grupie if () {} else {}instrukcji.

Za każdym razem funkcja przełącznika jest taka sama, ale polecenie, które dostarczamy, zmienia się.

do.this <- "T1"

switch(do.this,
    T1={X <- t(mtcars)
        colSums(mtcars)%*%X
    },
    T2={X <- colMeans(mtcars)
        outer(X, X)
    },
    stop("Enter something that switches me!")
)
#########################################################
do.this <- "T2"

switch(do.this,
    T1={X <- t(mtcars)
        colSums(mtcars)%*%X
    },
    T2={X <- colMeans(mtcars)
        outer(X, X)
    },
    stop("Enter something that switches me!")
)
########################################################
do.this <- "T3"

switch(do.this,
    T1={X <- t(mtcars)
        colSums(mtcars)%*%X
    },
    T2={X <- colMeans(mtcars)
        outer(X, X)
    },
    stop("Enter something that switches me!")
)

Tutaj znajduje się wewnątrz funkcji:

FUN <- function(df, do.this){
    switch(do.this,
        T1={X <- t(df)
            P <- colSums(df)%*%X
        },
        T2={X <- colMeans(df)
            P <- outer(X, X)
        },
        stop("Enter something that switches me!")
    )
    return(P)
}

FUN(mtcars, "T1")
FUN(mtcars, "T2")
FUN(mtcars, "T3")
Tyler Rinker
źródło
0

To jest bardziej ogólna odpowiedź na brakującą konstrukcję „Select cond1, stmt1, ... else stmtelse” w R. Jest trochę gazowa, ale działa i przypomina instrukcję switch obecną w C

while (TRUE) {
  if (is.na(val)) {
    val <- "NULL"
    break
  }
  if (inherits(val, "POSIXct") || inherits(val, "POSIXt")) {
    val <- paste0("#",  format(val, "%Y-%m-%d %H:%M:%S"), "#")
    break
  }
  if (inherits(val, "Date")) {
    val <- paste0("#",  format(val, "%Y-%m-%d"), "#")
    break
  }
  if (is.numeric(val)) break
  val <- paste0("'", gsub("'", "''", val), "'")
  break
}
Rolf L.
źródło