elNamed() to safely subset from named lists and vectors

2025-06-19

I’ve always been annoyed by how subsetting missing elements by name had different behaviors for lists vs. vectors.

Base behaviors

For named lists, subsetting with a non-existent name returns a NULL.

list(a = 1)[["b"]]
#> NULL

For named vectors, it errors with [[.

c(a = 1)[["b"]]
#> subscript out of bounds

The case of [ is interesting because it returns a NA.

c(a = 1)["b"]
#> <NA> 
#>   NA 

I get why, but it’s not so useful. It breaks nice equivalencies between lists and vectors.

elNamed() to subset by name

Then I discovered elNamed() from {methods}. It’s a sister of el() that subsets by name (vs. position):

el(c(a = 1), 1)
#> [1] 1
elNamed(c(a = 1), "a")
#> [1] 1

What’s kinda cool about elNamed() is that it returns NULL for unmatched names, for both lists and vectors.

elNamed(list(a = 1), "b")
#> NULL
elNamed(c(a = 1), "b")
#> NULL

And you can even turn it into an assertion!

elNamed(list(a = 1), "b", mustFind = TRUE)
#> 'b' is not one of the element names
elNamed(c(a = 1), "b", mustFind = TRUE)
#> 'b' is not one of the element names

?elNamed says it’s for “compatibility with S+”!

I don’t actually use elNamed() in practice, though.

But cool find nonetheless :)


This post was adapted from a Mastodon exchange: https://fosstodon.org/@yjunechoe/111383917758940010

sessionInfo()

Session info
sessionInfo()
#> R version 4.4.1 (2024-06-14 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26100)
#> 
#> Matrix products: default
#> 
#> 
#> locale:
#> [1] LC_COLLATE=English_United States.utf8 
#> [2] LC_CTYPE=English_United States.utf8   
#> [3] LC_MONETARY=English_United States.utf8
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.utf8    
#> 
#> time zone: America/New_York
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#> [1] compiler_4.4.1   litedown_0.7.1   tools_4.4.1      codetools_0.2-20
#> [5] xfun_0.52        commonmark_1.9.5