Home > Software engineering >  purrr return a list of different length for every element
purrr return a list of different length for every element

Time:10-27

I have a strange issue with map. My goal is to return a list for every element. Conditional on the element I want a list of different length (or at least different logic applied to it). This seems to be very difficult and map is returning all kinds of values (see below):

map(1:2, ~ list(.x, .x   1))
# returns list(list(1,2), list(2,3)

map(1:2, ~ ifelse(.x > 1,
                  list(.x, .x   1),
                  list(.x, .x)))
# returns list(list(1), list(2))

map(1:2, ~ case_when(.x > 1 ~ list(.x, .x   1),
                     TRUE ~ list(.x)))
# returns list(list(1,1), list(2,3)

I found two methods to solve this:

# Add a list around it and then remove the list
map(1:2, ~ ifelse(.x > 1,
                  list(list(.x, .x   1)),
                  list(.x))) %>%
  map(., ~.[[1]])

# Use a two step map_if
map_if(1:2, ~.x > 1, 
       ~list(.x, .x   1)) %>% 
  map_if(is.integer, ~list(.x))

Both feel a little weird to me.. What is the best practice in this regard?

CodePudding user response:

We could use if/else instead of ifelse or case_when as these require all arguments to be of same length (unless we replicate) i.e. the testis oflength` 1

library(purrr)
map(1:2, ~ if(.x > 1) list(.x, .x   1) else list(.x, .x))

-output

[[1]]
[[1]][[1]]
[1] 1

[[1]][[2]]
[1] 1


[[2]]
[[2]][[1]]
[1] 2

[[2]][[2]]
[1] 3

NOTE: Here each element from the vector is looped and thus we don't need an ifelse. If we want to use it anyway, do the ifelse and wrap the output with the element looped in a list

map(1:2, ~ list(.x, ifelse(.x > 1,
                  .x   1,
                  .x)))

-output

[[1]]
[[1]][[1]]
[1] 1

[[1]][[2]]
[1] 1


[[2]]
[[2]][[1]]
[1] 2

[[2]][[2]]
[1] 3

CodePudding user response:

What about something like this:

library(tidyverse)

map(1:2, \(x) {test <- list(x, ` `(x > 1)   x); test[!duplicated(test)]})
#> [[1]]
#> [[1]][[1]]
#> [1] 1
#> 
#> 
#> [[2]]
#> [[2]][[1]]
#> [1] 2
#> 
#> [[2]][[2]]
#> [1] 3
  • Related