debbybeginner
debbybeginner

Reputation: 79

Using `case_when()` instead of `if_else`

I'm trying to use case_when() instead of if(){else} when I ran into some problems:

# if_else version:
(x<- c("apple", "orange", "grapes", "kiwi"))
longstr <- function(x, delim = ",") {
  n <- length(x)
  if (n == 0) {
    ""
  } else if (n == 1) {
    x
  } else if (n == 2) {
    str_c(x[[1]], "&", x[[2]], sep = " ")
  } else {
    front <- str_c(x[seq_len(n - 1)], delim)
    back <- str_c("&", x[[n]], sep = " ")
    str_c(c(front, back), collapse = " ")
  }
}

longstr(x) # gives "apple, orange, grapes, & kiwi"
longstr(c("pea", "pod") # gives "pea & pod"
longstr("egg") # gives "egg"

but somehow when I rewrite this using case_when, things start to be weird:

# case_when version:
longstr2 <- function(x, delim = ",") {
  n <- length(x)
  case_when(
    n == 0 ~ "",
    n == 1 ~ x,
    n == 2 ~ str_c(x[1], "&", x[2], sep = " "),   # weird 1: I can't use x[[1]], but must use only x[1] here
    TRUE ~ {
      not_last <- str_c(x[seq_len(n - 1)], delim)
      last <- str_c("&", x[[n]], sep = " ")       # but somehow here I can still use x[[n]]
      (str_c(c(not_last, last), collapse = " "))}
  )
}

# the weirdest thing:
longstr2(x) 
    # gives "apple, orange, grapes, & kiwi" "apple, orange, grapes, & kiwi" "apple, orange, grapes, & kiwi" "apple, orange, grapes, & kiwi"
    # I don't know why it repeats 4 times
longstr2(c("pea", "pod") 
    # gives "pea & pod" "pea & pod"
    # here it repeats 2 times
longstr2("egg") # gives "egg"

I know somehow the weird repeat is linked to my n, but I don't know exactly where it went wrong. Any pointer appreciated! thank you!

Upvotes: 0

Views: 1086

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 388862

The only change that you need to make is when n = 1 return x[1] so that the length of output is always the same. Unlike, if/else case_when executes it's RHS irrespective of the condition it satisfies hence you see multiple values of the same output.

library(dplyr)
library(stringr)

longstr2 <- function(x, delim = ",") {
  n <- length(x)
  case_when(
    n == 0 ~ "",
    n == 1 ~ x[1],
    n == 2 ~ str_c(x[1], "&", x[2], sep = " "),   
    TRUE ~ {
      not_last <- str_c(x[seq_len(n - 1)], delim)
      last <- str_c("&", x[[n]], sep = " ") 
      (str_c(c(not_last, last), collapse = " "))}
  )
}

longstr2(x) 
#[1] "apple, orange, grapes, & kiwi"

longstr2(c("pea", "pod"))
#[1] "pea & pod"

longstr2("egg") 
#[1] "egg"

Consider this simple example to understand what I mean by case_when executes it's RHS condition irrespective of the condition.

n <- 'a'
case_when(is.numeric(n) ~ sqrt(n), TRUE ~ n)

This returns

Error in sqrt(n) : non-numeric argument to mathematical function

This is the same error that you get when you do sqrt('a') but one would think that is.numeric(n) is FALSE so it should not even execute sqrt(n) but that is not the case.

Upvotes: 2

Related Questions