Multi-value purrr::pluck?

This seems like a basic question (almost embarrassingly-so) and perhaps I'm just missing something obvious ... but is there any way to pluck a sublist with purrr?
More specifically, here's an initial list:

l <- list(a = "foo", b = "bar", c = "baz")

And I want to return a new (sub-)list with elements a and b.
Normally, I'd just do 'base' R sub-listing:

l[c("a", "b")]

But this doesn't provide the nice .default handling of pluck which I've really come to appreciate.
Pluck (more-or-less) 'replaces' [[, but is there a purrr equivalent for replacing [?

(I know I can create a moral equivalent using various map* functions, as well as simply pluck-ing twice (in the above example), but I just want to make sure that I'm not overlooking an already-in-place function/pattern for this!)

2 Likes
library(purrr)
library(magrittr)
#> 
#> Attaching package: 'magrittr'
#> The following object is masked from 'package:purrr':
#> 
#>     set_names
l <- list(a = "foo", b = "bar", c = "baz")

purrr::map(c("a", "b"), ~ l[.]) %>% unlist()
#>     a     b 
#> "foo" "bar"

The very existence of pluck just blew my mind :open_mouth:

2 Likes

What about using extract from magrittr?

extract is just an alias for [, so it won't add the .default handling that @mmuurr is looking for. I'm not aware of anything that works quite like that, unfortunately -- it seems like a potentially worthwhile helper function (though it'd likely have to be separate from pluck).

A related GitHub issue: export magrittr::extract()? · Issue #223 · tidyverse/purrr · GitHub

It doesn't really add much to this thread, but confirms that you're not alone and that this doesn't really exist. Also points out that another way to describe the request is (sort of) a select() method for lists.

4 Likes

There's clearly a need for "muti-value pluck". You can call it select, but it really comes down to extending flexibility of "pluck" to retrieving multiple values from the same level of list, as described by @jennybryan in that github issue. For the example above, you can probably get away with:

purrr::map(purrr::set_names(c("a", "b")), `
          ~purrr::pluck(l, .x, .default = NA_character_))

PS. Btw, issue is worth re-opening, imo.

1 Like