balikezir
balikezir

Reputation: 31

R switch() how to compare cases to a vector?

I've got a little issue with the switch statement in R. The following code is OK ... :

    value = "B"
  switch(value, 
         "A"={
           print("value = A")
         },
         "B"={
           print("value = B")
         },
         "C"={
           print("value = C")
         },
         {
           print("Other !!!")
        }
        )

It returns :

[1] "value = B"

... but I would like to compare value to a vector's values like this :

mychr = c("A","B", "C")
  value = "B"
  switch(value, 
         mychr[1]={
           print(mychr[1])
         },
         mychr[2]={
           print(mychr[2])
         },
         mychr[3]={
           print(mychr[3])
         },
         {
           print("Other !!!")
         }
         )

And that doesn't work.

I can do this with "if else", or with the first code but I would like to understand the mistake.

Upvotes: 3

Views: 3255

Answers (4)

user5957401
user5957401

Reputation: 228

Try using vapply.

i.e. in your case

vapply(mychr,switch,"",...SWITCH ARGS...)

I think what you would want is:

vapply(mychr,switch,"",
               mychr[1]=mychr[1],mychr[2]=mychr[2],mychr[3]=mychr[3],"Other !!!")

Upvotes: 0

John
John

Reputation: 23758

Your mistake is that the switch alternatives require literal names and can't have a variable name. You're naming the arguments of the function and they internally become names of items in a list. In fact, the "" aren't necessary around your A, B, C in your first example. Knowing that, the problem becomes more obvious. Try assigning b <- "B" and then using b as the second switch item. That will fail as well because it's not going to resolve the variable name, just take it as a literal. In your case it fails with a syntax problem because alist[1] isn't a valid alternative label without quotes.

Similar restrictions are placed on switch statements in other languages as well. Think of the alternatives in the switch as being labelled like names of items in a list structure. They can be pretty much anything quoted but they don't need quotes and then there are restrictions on what they can be. What they cannot be is variable.

As you recognize in your question, there are alternative ways to do this. Here's a concise one that will be much faster than a switch statement (even if you did manage to solve the variable list items problem indirectly with a call function).

i <- which(alist == value)
if (length(i) == 1){
    print( paste0( 'value = ', alist[i]) )
}else {
    print( 'Other !!' ) }

Upvotes: 3

jdharrison
jdharrison

Reputation: 30425

Im sure there are easier ways but you can use alist and do.call

xlist = c("A","B", "C")
value = "B"
myList <- alist(print(xlist[1]), print(xlist[2]), print(xlist[3]), print("Other !!!"))
myList <- setNames(myList, c(xlist, ''))
do.call(switch, c(EXPR = value, myList))

Examples:

> value = "D"
> do.call(switch, c(EXPR = value, myList))
[1] "Other !!!"
> value = "A"
> do.call(switch, c(EXPR = value, myList))
[1] "A"
> value = "C"
> do.call(switch, c(EXPR = value, myList))
[1] "C"
> value = "B"
> do.call(switch, c(EXPR = value, myList))
[1] "B"

Upvotes: 4

nico
nico

Reputation: 51640

The == operator works on vectors, so what you need is just:

> a <- c("A", "B", "C")
> a
[1] "A" "B" "C"
> b <- "B"
> b == a
[1] FALSE  TRUE FALSE

Alternatively, you can use which

> which(a == b)
[1] 2

Note that can return several elements if a contains more than one instance of b

You can then proceed using an if or ifelse or switch statement on the result.

PS: you should avoid using list as a variable name, as it is a standard function in R

Upvotes: 1

Related Questions