Reputation: 79
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
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