Subset a nested list to get all the lower level lists with the same characters in their names

I'd like to extract all the nested lists with M_ in their names (M_ can be anywhere in the string, but in this example, at the start) and save them to a new list without typing out the specific item.

dput(dlist4)
list(A = list(a = structure(1:4, dim = c(2L, 2L)), b = structure(2:5, dim = c(2L, 
2L))), G = list(a = structure(10:13, dim = c(2L, 2L)), b = structure(5:8, dim = c(2L, 
2L))), M_1 = list(a = structure(10:13, dim = c(2L, 2L)), b = structure(5:8, dim = c(2L, 
2L))), M_2 = list(a = structure(2:5, dim = c(2L, 2L)), b = structure(5:8, dim = c(2L, 
2L))))

For this small list, I can do dlist4[c("M_1", "M_2")], but imagine a larger nested list with hundreds of lower-level lists whose names either contain or start with "M_". Then, typing them all out would not be possible.

dlist4 %>% pluck("M_") gives NULL with no error so I don't know what's wrong with my code.

dlist4 %>% map(., ~{pluck("M_")}) returns an empty list and picks the wrong elements (A and G)

$A
[1] "M_"

$G
[1] "M_"

$M_1
[1] "M_"

$M_2
[1] "M_"

Combining the 2 suggestions in the Stackoverflow comments, I got

dlist4[contains("M", names(dlist4))]
Error:
! `contains()` must be used within a *selecting* function.
ℹ See <https://tidyselect.r-lib.org/reference/faq-selection-context.html>.
Run `rlang::last_error()` to see where the error occurred.

or

dlist4 %>%select.list(., contains(names(.), "M"))
1: list(a = 1:4, b = 2:5)
2: list(a = 10:13, b = 5:8)
3: list(a = 10:13, b = 5:8)
4: list(a = 2:5, b = 5:8)

Selection: 

or

dlist4 %>% select(contains(names(.), "M"))
Error in `select()`:
! `select()` doesn't handle lists.
Run `rlang::last_error()` to see where the error occurred.

Here is the original StackOverflow post: r - Subset a nested list to get all the lower level lists with the same characters in their names - Stack Overflow

I tried str_detect() and it seems to work. I modified one of the names to test a case where M_ was not at the beginning of the name.

library(stringr)
dlist4 <- list(A = list(a = structure(1:4, dim = c(2L, 2L)), 
                        b = structure(2:5, dim = c(2L,2L))), 
               G = list(a = structure(10:13, dim = c(2L, 2L)), 
                        b = structure(5:8, dim = c(2L, 2L))), 
               M_1 = list(a = structure(10:13, dim = c(2L, 2L)), 
                          b = structure(5:8, dim = c(2L, 2L))), 
               N_2_M_3 = list(a = structure(2:5, dim = c(2L, 2L)), 
                          b = structure(5:8, dim = c(2L, 2L))))

dlist4[str_detect(names(dlist4), "M_")]
#> $M_1
#> $M_1$a
#>      [,1] [,2]
#> [1,]   10   12
#> [2,]   11   13
#> 
#> $M_1$b
#>      [,1] [,2]
#> [1,]    5    7
#> [2,]    6    8
#> 
#> 
#> $N_2_M_3
#> $N_2_M_3$a
#>      [,1] [,2]
#> [1,]    2    4
#> [2,]    3    5
#> 
#> $N_2_M_3$b
#>      [,1] [,2]
#> [1,]    5    7
#> [2,]    6    8

Created on 2022-05-26 by the reprex package (v2.0.1)

1 Like

Thank you very much for making my example better.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.