Flattening and simplification

purrr 1.1.0

purrr
purrr 1.0.0 has new functions for flattening and simplifying lists.
Published

December 20, 2022

Install purrr 1.0.0 with:

pak::pak("cran/purrr@1.0.0")

Load the package with:

Flattening

list_flatten() removes one layer of hierarchy from a list:

x <- list(1, list(2, list(3, 4), 5))
x |> str()
List of 2
 $ : num 1
 $ :List of 3
  ..$ : num 2
  ..$ :List of 2
  .. ..$ : num 3
  .. ..$ : num 4
  ..$ : num 5
x |> list_flatten() |> str()
List of 4
 $ : num 1
 $ : num 2
 $ :List of 2
  ..$ : num 3
  ..$ : num 4
 $ : num 5
x |> list_flatten() |> list_flatten() |> str()
List of 5
 $ : num 1
 $ : num 2
 $ : num 3
 $ : num 4
 $ : num 5

list_flatten() always returns a list; once a list is as flat as it can get (i.e. none of its children contain lists), it leaves the input unchanged.

List of 5
 $ : num 1
 $ : num 2
 $ : num 3
 $ : num 4
 $ : num 5

Simplification

list_simplify() maintains the length of the input, but produces a simpler type:

x <- list(1, 2, 3)
typeof(x)
[1] "list"
y <-
  x |> list_simplify()

y
[1] 1 2 3
[1] "double"

A few rules for list_simplify():

  • It will only succeed if every element has length 1
list_simplify(list(1, 2, 3:4))
Error in `list_simplify()`:
! `x[[3]]` must have size 1, not size 2.
  • All the components must be compatible
list_simplify(list(1, 2, "a"))
Error in `list_simplify()`:
! Can't combine `<list>[[1]]` <double> and `<list>[[3]]` <character>.

If you need to simplify if it’s possible, but otherwise leave the input unchanged, use strict = FALSE:

list_simplify(list(1, 2, "a"), strict = FALSE)
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] "a"

If you want to be specific about the type you want, list_simplify() can take the same prototype argument as map_vec():

list(1, 2, 3) |> list_simplify(ptype = integer())
[1] 1 2 3

Concatenation

map_dfr() and map_dfc() (and the map2 and pmap) variants are superseded. Consider switching to an explicit call to list_rbind() or list_cbind() instead:

paths |> map_dfr(read_csv, .id = "path")
paths |> 
  map(read_csv) |> 
  list_rbind(names_to = "path")

Learn more