Extract names of second [given] level of nested list in R
Asked Answered
S

3

10

I have a nested list. Each level of this list is named (as in provided dummy example). I want to extract the names (unique) from the 2nd level of my initial list, so I will be able to use them in some further operations.

I know how to do it in two steps, but I wonder whether there is more efficient/elegant solution. Also I wonder whether the regex approach would be faster (I am noob at regex).

Here is a dummy list:

x <- list(one = list(one_1 = list(seq = 1:9, start = 1, end = 5),
                     one_2 = list(seq = 2:11, start = 2, end = 6),
                     one_3 = list(seq = 3:12, start = 3, end = 7)),
          two = list(two_1 = list(seq = 1:13, start = 8, end = 222),
                     two_2 = list(seq = 1:14, start = 13, end = 54)))

And here is my code:

allnames <- names(rapply(x, function(x) head(x, 1)))
desirednames <- unique(sapply(strsplit(allnames, ".", fixed=TRUE), "[", 2))
Seismology answered 6/7, 2022 at 11:25 Comment(0)
F
8

A possible solution, based on purrr::map_depth:

library(tidyverse)

map_depth(x, 1, names) %>% unlist(use.names = F)

#> [1] "one_1" "one_2" "one_3" "two_1" "two_2"
Froebel answered 6/7, 2022 at 11:30 Comment(1)
Why not map(x, names)?Shaeshaef
M
9

Solution for second level in base R:

unlist(lapply(names(x), function(n) names(x[[n]])))
[1] "one_1" "one_2" "one_3" "two_1" "two_2"
Milliemillieme answered 6/7, 2022 at 11:35 Comment(3)
Isn't unlist more "costly" than purrr::map approach?Seismology
No need to load a package ! You can check using microbenchmark package on small and big datasetMilliemillieme
unlist(lapply(x, names)) or unname(unlist(lapply(x, names)))Shaeshaef
F
8

A possible solution, based on purrr::map_depth:

library(tidyverse)

map_depth(x, 1, names) %>% unlist(use.names = F)

#> [1] "one_1" "one_2" "one_3" "two_1" "two_2"
Froebel answered 6/7, 2022 at 11:30 Comment(1)
Why not map(x, names)?Shaeshaef
U
3

A concise way of doing this:

unlist(lapply(x, \(x) attributes(x)[['names']])) 
#    one1    one2    one3    two1    two2 
# "one_1" "one_2" "one_3" "two_1" "two_2"

If the list elements just have the "names" attribute, this simplifies to:

unlist(lapply(x, attributes))
# one.names1 one.names2 one.names3 two.names1 two.names2 
#    "one_1"    "one_2"    "one_3"    "two_1"    "two_2" 

If the names annoy you, pipe it into unname.

unlist(lapply(x, attributes)) |> unname()
# [1] "one_1" "one_2" "one_3" "two_1" "two_2"
Ulyanovsk answered 6/7, 2022 at 14:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.