From 8fbda1cf2e1399b95179ef85bc34ac524f1e64a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20M=C3=BCcke?= Date: Wed, 5 Feb 2025 21:58:27 +0100 Subject: [PATCH] feat: add compact (#129) * feat: add compact * docs: missing document --- NAMESPACE | 1 + R/purrr_map.R | 7 +++++++ man/compat-map.Rd | 4 ++++ tests/testthat/test_map.R | 9 +++++++++ 4 files changed, 21 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index 7104f258..71be46d0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -63,6 +63,7 @@ export(chunk_vector) export(cite_bib) export(clbk) export(clbks) +export(compact) export(compose) export(compute_mode) export(count_missing) diff --git a/R/purrr_map.R b/R/purrr_map.R index 9f61d94b..71acd540 100644 --- a/R/purrr_map.R +++ b/R/purrr_map.R @@ -13,6 +13,7 @@ #' * `map_at()` applies `.f` to each element of `.x` referenced by `.at`. All other elements remain unchanged. #' * `keep()` keeps those elements of `.x` where predicate `.p` evaluates to `TRUE`. #' * `discard()` discards those elements of `.x` where predicate `.p` evaluates to `TRUE`. +#' * `compact()` discards elements of `.x` that are `NULL`. #' * `every()` is `TRUE` if predicate `.p` evaluates to `TRUE` for each `.x`. #' * `some()` is `TRUE` if predicate `.p` evaluates to `TRUE` for at least one `.x`. #' * `detect()` returns the first element where predicate `.p` evaluates to `TRUE`. @@ -272,6 +273,12 @@ discard.data.table = function(.x, .p, ...) { # nolint .x[, is.na(.sel) | !.sel, with = FALSE] } +#' @export +#' @rdname compat-map +compact = function(.x) { # nolint + .x[as.logical(lengths(.x))] +} + #' @export #' @rdname compat-map map_if = function(.x, .p, .f, ...) { diff --git a/man/compat-map.Rd b/man/compat-map.Rd index 38dee256..020aabed 100644 --- a/man/compat-map.Rd +++ b/man/compat-map.Rd @@ -27,6 +27,7 @@ \alias{imap_dtc} \alias{keep} \alias{discard} +\alias{compact} \alias{map_if} \alias{map_if.default} \alias{map_at} @@ -88,6 +89,8 @@ keep(.x, .f, ...) discard(.x, .p, ...) +compact(.x) + map_if(.x, .p, .f, ...) \method{map_if}{default}(.x, .p, .f, ...) @@ -140,6 +143,7 @@ each vector of \code{.x}, then the second element of \code{.x}, and so on. \item \code{map_at()} applies \code{.f} to each element of \code{.x} referenced by \code{.at}. All other elements remain unchanged. \item \code{keep()} keeps those elements of \code{.x} where predicate \code{.p} evaluates to \code{TRUE}. \item \code{discard()} discards those elements of \code{.x} where predicate \code{.p} evaluates to \code{TRUE}. +\item \code{compact()} discards elements of \code{.x} that are \code{NULL}. \item \code{every()} is \code{TRUE} if predicate \code{.p} evaluates to \code{TRUE} for each \code{.x}. \item \code{some()} is \code{TRUE} if predicate \code{.p} evaluates to \code{TRUE} for at least one \code{.x}. \item \code{detect()} returns the first element where predicate \code{.p} evaluates to \code{TRUE}. diff --git a/tests/testthat/test_map.R b/tests/testthat/test_map.R index 1e2f0b0e..7ce457a3 100644 --- a/tests/testthat/test_map.R +++ b/tests/testthat/test_map.R @@ -201,6 +201,15 @@ test_that("detect", { expect_null(out) }) +test_that("compact", { + x = list(a = 1:3, b = c("a", "b"), c = NULL, d = NULL) + out = compact(x) + expect_identical(out, x[1:2]) + x = list(a = 1:3, b = c("a", "b"), c = runif(3)) + out = compact(x) + expect_identical(out, x) +}) + test_that("pmap does not segfault (#56)", { expect_error(pmap(1:4, function(x) x), "list") })