tidyverse / funs

Collection of low-level functions for working with vctrs
Other
34 stars 7 forks source link

coalesce #32

Closed hadley closed 4 years ago

hadley commented 4 years ago

From #17, by @DavisVaughan

library(rlang)
library(vctrs)

vec_coalesce <- function(..., .ptype = NULL) {
  args <- list2(...)

  n_args <- vec_size(args) 

  if (n_args == 0L) {
    return(NULL)
  }

  if (n_args == 1L) {
    out <- args[[1L]]
    return(out)
  }

  args <- vec_cast_common(!!! args, .to = .ptype)
  args <- vec_recycle_common(!!! args)

  out <- args[[1L]]
  args <- args[-1L]

  for (arg in args) {
    is_na <- vec_equal_na(out)

    if (!any(is_na)) {
      break
    }

    vec_slice(out, is_na) <- vec_slice(arg, is_na)
  }

  out
}

vec_coalesce()
#> NULL

vec_coalesce(1, 0)
#> [1] 1

vec_coalesce(1, FALSE, .ptype = logical())
#> [1] TRUE

vec_coalesce(NA, 1)
#> [1] 1

vec_coalesce(c(1, NA, 2), 0L)
#> [1] 1 0 2

vec_coalesce(
  data.frame(x = c(1, NA, 3)), 
  data.frame(x = 2)
)
#>   x
#> 1 1
#> 2 2
#> 3 3

# a bit odd, but this technically makes sense
vec_coalesce(
  data.frame(x = c(1, NA)), 
  data.frame(x = 2, y = 3)
)
#>   x  y
#> 1 1 NA
#> 2 2  3

vec_coalesce(
  factor(c("x", "y", NA, "x", NA)),
  factor("MISSING!")
)
#> [1] x        y        MISSING! x        MISSING!
#> Levels: x y MISSING!

# Common size is used as the reference
vec_coalesce(
  1,
  c(1, 2, 3)
)
#> [1] 1 1 1

vec_coalesce(
  NA,
  c(1, 2, 3)
)
#> [1] 1 2 3