I want to filter a nested list by an attribute at .depth = 2
. I can extract the attribute with modify_depth(x, 2, ~attr(.x, "p"))
, but I do not know how to include a keep
clause to filter the desired elements. In other words, how do I keep
at .depth = 2
?
Never mind--I just flattened the list before keeping, e.g. flatten(x) %>% keep(~attr(.x, "p"))
Example data:
library(purrr)
y <- "foo"
attr(y, "p") <- FALSE
z <- "bar"
attr(z, "p") <- TRUE
x <- list(list(y, z), list(y, y, y), list(z))
str(x)
# List of 3
# $ :List of 2
# ..$ : atomic [1:1] foo
# .. ..- attr(*, "p")= logi FALSE
# ..$ : atomic [1:1] bar
# .. ..- attr(*, "p")= logi TRUE
# $ :List of 3
# ..$ : atomic [1:1] foo
# .. ..- attr(*, "p")= logi FALSE
# ..$ : atomic [1:1] foo
# .. ..- attr(*, "p")= logi FALSE
# ..$ : atomic [1:1] foo
# .. ..- attr(*, "p")= logi FALSE
# $ :List of 1
# ..$ : atomic [1:1] bar
# .. ..- attr(*, "p")= logi TRUE
Your solution:
res_1 <- flatten(x) %>% keep(~attr(.x, "p"))
str(res_1)
# List of 2
# $ : atomic [1:1] bar
# ..- attr(*, "p")= logi TRUE
# $ : atomic [1:1] bar
# ..- attr(*, "p")= logi TRUE
Alternative solution that keeps the nested structure: to "keep at depth 2", we simply map (equivalent to "modify at depth 1") the keep function:
res_2 <- map(x, keep, attr, "p")
str(res_2)
# List of 3
# $ :List of 1
# ..$ : atomic [1:1] bar
# .. ..- attr(*, "p")= logi TRUE
# $ : list()
# $ :List of 1
# ..$ : atomic [1:1] bar
# .. ..- attr(*, "p")= logi TRUE
1 Like
That is more elegant, thanks! I forgot to add the filtering criteria to keep
, so I think I'd have to go something like this?
res_2 <- map(x, ~keep(., ~attr(., "p") %in% as.character(1:5)))