purrr
purrr copied to clipboard
Equivalent of has_element() for element names in a list?
I'm wondering if there is a purrr function that detects whether an element with a given name appears in a list. For example, in the following code:
> library(purrr)
> ingredients <- list(tomatoes = 3, radishes = 5, cucumbers = 2)
I'm looking for a simple way to find out if the ingredients
list contains "tomatoes".
I tried the has_element()
function, but it only works with the values in a list, not the names:
> has_element(ingredients, "tomatoes")
[1] FALSE
> has_element(ingredients, 3)
[1] TRUE
This makes sense to me as you probably want to avoid the situation where you accidentally match a name in the list when you are looking to match a value instead.
I ended up writing a function like this:
has_element_named <- function(list, name){!is.null(list[[name]])}
> has_element_named(ingredients, "tomatoes")
[1] TRUE
> has_element_named(ingredients, "celery")
[1] FALSE
But this runs the same risk: that it will also match a value as well as the name:
> has_element_named(ingredients, 3)
[1] TRUE
This might be desirable in some circumstances, but most people will probably want to match against either names or values, not both. So I wrote:
has_element_called <- function(list, name){name %in% names(list)}
> has_element_called(ingredients, "tomatoes")
[1] TRUE
> has_element_called(ingredients, "celery")
[1] FALSE
> has_element_called(ingredients, 3)
[1] FALSE
Which is simple enough to do I guess, but there may be a better designed or robust function that could be written (or maybe it already exists I just can't find it). This function doesn't, for example, account for any depth in the list you are matching against.
FWIW rlang::has_name()
does this.
ingredients <- list(tomatoes = 3, radishes = 5, cucumbers = 2)
rlang::has_name(ingredients, "radishes")
#> [1] TRUE
rlang::has_name(ingredients, "onions")
#> [1] FALSE
Created on 2018-11-03 by the reprex package (v0.2.1)
And for checking a position exists, I would use length(x) >= n
.
This is basically the same as can_pluck()
Is there any way to look for an element name that is nested deeper in lists of lists?
Might be worth generalising to has_index(x, idx)
which would if idx
was integer, character, or list (i.e. recursively).
Maybe is_pluckable()
? Or pluck_exists()
?