6.4 Fizzbuzz
fizzbuzz <- function(x) {
# these two lines check that x is a valid input
stopifnot(length(x) == 1)
stopifnot(is.numeric(x))
if (!(x %% 3) && !(x %% 5)) {
"fizzbuzz"
} else if (!(x %% 3)) {
"fizz"
} else if (!(x %% 5)) {
"buzz"
} else {
# ensure that the function returns a character vector
as.character(x)
}
}
Check modulo 3 only once
fizzbuzz2 <- function(x) {
# these two lines check that x is a valid input
stopifnot(length(x) == 1)
stopifnot(is.numeric(x))
if (!(x %% 3)) {
if (!(x %% 5)) {
"fizzbuzz"
} else {
"fizz"
}
} else if (!(x %% 5)) {
"buzz"
} else {
# ensure that the function returns a character vector
as.character(x)
}
}
6.4.1 Vectorized conditionals
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
fizzbuzz_vec <- function(x) {
dplyr::case_when(
!(x %% 3) & !(x %% 5) ~ "fizzbuzz",
!(x %% 3) ~ "fizz",
!(x %% 5) ~ "buzz",
TRUE ~ as.character(x)
)
}
6.4.2 Multiple conditions
6.4.2.1 switch
6.4.2.2 cut
describe_temp <- function(temp) {
if (temp <= 0) {
"freezing"
} else if (temp <= 10) {
"cold"
} else if (temp <= 20) {
"cool"
} else if (temp <= 30) {
"warm"
} else {
"hot"
}
}
Current function can’t handle vectors
describe_temp(c(16, 61))
## Warning in if (temp <= 0) {: the condition has length > 1 and only the first
## element will be used
## Warning in if (temp <= 10) {: the condition has length > 1 and only the first
## element will be used
## Warning in if (temp <= 20) {: the condition has length > 1 and only the first
## element will be used
## [1] "cool"
How cut works:
cut(values, c(-Inf, -5, -1, 1, 7, Inf))
## [1] (-Inf,-5] (-Inf,-5] (-Inf,-5] (-Inf,-5] (-Inf,-5] (-Inf,-5] (-5,-1]
## [8] (-5,-1] (-5,-1] (-5,-1] (-1,1] (-1,1] (1,7] (1,7]
## [15] (1,7] (1,7] (1,7] (1,7] (7, Inf] (7, Inf] (7, Inf]
## Levels: (-Inf,-5] (-5,-1] (-1,1] (1,7] (7, Inf]