Skip to contents

Recursively flattens a list. Unlike the similar unlist(), it

  • always returns a list, i.e. wraps x in a list if necessary, and will never remove the last list level. Thus it is type-safe.

  • won't treat any of the list leafs specially (like unlist() does with factors). Thus leaf values will never be modified.

  • removes list names. unlist() concatenates nested names (separated by a dot).

Usage

as_flat_list(x, keep_attrs = TRUE, attrs_to_drop = "xfun_strict_list")

Arguments

x

An R object.

keep_attrs

Keep attributes (and thereby retain list structure of custom objects). A logical scalar.

attrs_to_drop

Attribute names which should never be kept. Only relevant if keep_attrs = TRUE. A character vector.

Value

A list.

Examples

library(magrittr)

nested_list <- list(1:3, list("foo", list("bar"))) %T>% str()
#> List of 2
#>  $ : int [1:3] 1 2 3
#>  $ :List of 2
#>   ..$ : chr "foo"
#>   ..$ :List of 1
#>   .. ..$ : chr "bar"

# unlike `unlist()` which also removes the last list tier in many cases...
unlist("foobar")
#> [1] "foobar"
unlist(nested_list) |> str()
#>  chr [1:5] "1" "2" "3" "foo" "bar"
# ...this function always returns an (unnested) list
pal::as_flat_list("foobar") |> str()
#> List of 1
#>  $ : chr "foobar"
pal::as_flat_list(nested_list) |> str()
#> List of 3
#>  $ : int [1:3] 1 2 3
#>  $ : chr "foo"
#>  $ : chr "bar"

nested_list <- list(list(factor("a"), factor("b")), factor("c")) %T>% str()
#> List of 2
#>  $ :List of 2
#>   ..$ : Factor w/ 1 level "a": 1
#>   ..$ : Factor w/ 1 level "b": 1
#>  $ : Factor w/ 1 level "c": 1

# unlike `unlist()` which combines factors...
unlist(nested_list) |> str()
#>  Factor w/ 3 levels "a","b","c": 1 2 3
# ...this function does not modify the list elements
pal::as_flat_list(nested_list) |> str()
#> List of 3
#>  $ : Factor w/ 1 level "a": 1
#>  $ : Factor w/ 1 level "b": 1
#>  $ : Factor w/ 1 level "c": 1

nested_list <-
  list(c(list(1L), list(tibble::tibble(a = list(1.1, "2")))),
       list(tibble::as_tibble(mtcars[1:2, ]))) %T>%
  str()
#> List of 2
#>  $ :List of 2
#>   ..$ : int 1
#>   ..$ : tibble [2 × 1] (S3: tbl_df/tbl/data.frame)
#>   .. ..$ a:List of 2
#>   .. .. ..$ : num 1.1
#>   .. .. ..$ : chr "2"
#>  $ :List of 1
#>   ..$ : tibble [2 × 11] (S3: tbl_df/tbl/data.frame)
#>   .. ..$ mpg : num [1:2] 21 21
#>   .. ..$ cyl : num [1:2] 6 6
#>   .. ..$ disp: num [1:2] 160 160
#>   .. ..$ hp  : num [1:2] 110 110
#>   .. ..$ drat: num [1:2] 3.9 3.9
#>   .. ..$ wt  : num [1:2] 2.62 2.88
#>   .. ..$ qsec: num [1:2] 16.5 17
#>   .. ..$ vs  : num [1:2] 0 0
#>   .. ..$ am  : num [1:2] 1 1
#>   .. ..$ gear: num [1:2] 4 4
#>   .. ..$ carb: num [1:2] 4 4
nested_list_2 <- list(1:3, xfun::strict_list(list(list("buried deep")))) %T>% str()
#> List of 2
#>  $ : int [1:3] 1 2 3
#>  $ :List of 1
#>   ..$ :List of 1
#>   .. ..$ :List of 1
#>   .. .. ..$ : chr "buried deep"
#>   ..- attr(*, "class")= chr "xfun_strict_list"

# by default, attributes and thus custom objects (except `xfun_strict_list`) are retained, i.e.
# not flattened...
pal::as_flat_list(nested_list) |> str()
#> List of 3
#>  $ : int 1
#>  $ : tibble [2 × 1] (S3: tbl_df/tbl/data.frame)
#>   ..$ a:List of 2
#>   .. ..$ : num 1.1
#>   .. ..$ : chr "2"
#>  $ : tibble [2 × 11] (S3: tbl_df/tbl/data.frame)
#>   ..$ mpg : num [1:2] 21 21
#>   ..$ cyl : num [1:2] 6 6
#>   ..$ disp: num [1:2] 160 160
#>   ..$ hp  : num [1:2] 110 110
#>   ..$ drat: num [1:2] 3.9 3.9
#>   ..$ wt  : num [1:2] 2.62 2.88
#>   ..$ qsec: num [1:2] 16.5 17
#>   ..$ vs  : num [1:2] 0 0
#>   ..$ am  : num [1:2] 1 1
#>   ..$ gear: num [1:2] 4 4
#>   ..$ carb: num [1:2] 4 4
pal::as_flat_list(nested_list_2) |> str()
#> List of 2
#>  $ : int [1:3] 1 2 3
#>  $ : chr "buried deep"
# ...but you can drop them and thereby flatten custom objects if needed...
pal::as_flat_list(nested_list, keep_attrs = FALSE) |> str()
#> List of 4
#>  $ : int 1
#>  $ : num 1.1
#>  $ : chr "2"
#>  $ : tibble [2 × 11] (S3: tbl_df/tbl/data.frame)
#>   ..$ mpg : num [1:2] 21 21
#>   ..$ cyl : num [1:2] 6 6
#>   ..$ disp: num [1:2] 160 160
#>   ..$ hp  : num [1:2] 110 110
#>   ..$ drat: num [1:2] 3.9 3.9
#>   ..$ wt  : num [1:2] 2.62 2.88
#>   ..$ qsec: num [1:2] 16.5 17
#>   ..$ vs  : num [1:2] 0 0
#>   ..$ am  : num [1:2] 1 1
#>   ..$ gear: num [1:2] 4 4
#>   ..$ carb: num [1:2] 4 4
# ...or retain `xfun_strict_list`s, too
pal::as_flat_list(nested_list_2, attrs_to_drop = NULL) |> str()
#> List of 2
#>  $ : int [1:3] 1 2 3
#>  $ :List of 1
#>   ..$ :List of 1
#>   .. ..$ :List of 1
#>   .. .. ..$ : chr "buried deep"
#>   ..- attr(*, "class")= chr "xfun_strict_list"