Reputation: 19405
Consider this convoluted and nested example (which, believe it or not arises for real in my dataset)
> nestedlist <- list(list('fakedata' = 'hello',
+ list(list('name'= list('john','litz'), 'age'= 30))),
+ list('fakedata' = 'there',
+ list(list('name'= list('frank','doe'), 'age'= 34))))
>
> nestedlist %>% str
List of 2
$ :List of 2
..$ fakedata: chr "hello"
..$ :List of 1
.. ..$ :List of 2
.. .. ..$ name:List of 2
.. .. .. ..$ : chr "john"
.. .. .. ..$ : chr "litz"
.. .. ..$ age : num 30
$ :List of 2
..$ fakedata: chr "there"
..$ :List of 1
.. ..$ :List of 2
.. .. ..$ name:List of 2
.. .. .. ..$ : chr "frank"
.. .. .. ..$ : chr "doe"
.. .. ..$ age : num 34
I am trying to use purrr
to extract elements from it. Something simple like extracting the fakedata
field works easily:
> purrr::map(nestedlist, 'fakedata')
[[1]]
[1] "hello"
[[2]]
[1] "there"
However, I am interested in the name
field. And in this case my purrr
solution does not work:
> purrr::map(nestedlist, list(1,1,'name'))
[[1]]
NULL
[[2]]
NULL
What is the issue here? Thanks!
Upvotes: 4
Views: 523
Reputation: 6244
Another option is to use rrapply()
in the rrapply
-package (an extension of base rapply()
), which is made exactly for this purpose:
library(rrapply) ## v1.2.1
## filter 'name' nodes as flat list
str(rrapply(nestedlist, classes = "list", condition = function(x, .xname) .xname == "name", how = "flatten"))
#> List of 2
#> $ name:List of 2
#> ..$ : chr "john"
#> ..$ : chr "litz"
#> $ name:List of 2
#> ..$ : chr "frank"
#> ..$ : chr "doe"
## prune 'name' nodes maintaining list structure
str(rrapply(nestedlist, classes = "list", condition = function(x, .xname) .xname == "name", how = "prune"))
#> List of 2
#> $ :List of 1
#> ..$ :List of 1
#> .. ..$ :List of 1
#> .. .. ..$ name:List of 2
#> .. .. .. ..$ : chr "john"
#> .. .. .. ..$ : chr "litz"
#> $ :List of 1
#> ..$ :List of 1
#> .. ..$ :List of 1
#> .. .. ..$ name:List of 2
#> .. .. .. ..$ : chr "frank"
#> .. .. .. ..$ : chr "doe"
Upvotes: 1
Reputation: 36
I was going to suggest the use of purrr::pluck()
, then then reading through the doco I discovered you could actually just use a purrr::map()
.
You're very close: you need to pass a list of accessors to map()
rather than a character vector, and there's an accessor you've missed.
nestedlist %>% map( list('data', 1, 'name') )
[[1]]
[[1]][[1]]
[1] "john"
[[1]][[2]]
[1] "litz"
[[2]]
[[2]][[1]]
[1] "frank"
[[2]][[2]]
[1] "doe"
Upvotes: 1