# Get and Set List Elements with magrittr

February 1, 2020
By

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

# Introduction

Did you know that the `magrittr` pipe, `%>%`, can be used for more than just `data.frame`s and `tibble`s? In this blog post, we look at how we can create get and set functions for list elements.

# Getting List Elements

First, let’s create a simple list.

``````z1 <- list(a = pi, b = 2.718, c = 0.57721)
z1
# \$a
# [1] 3.141593
#
# \$b
# [1] 2.718
#
# \$c
# [1] 0.57721``````

Let’s say we want to access an element of this list, typically we would use the `[[` function to do so.

``````z1[[2]]
# [1] 2.718``````

But let’s say we need to access this list as part of a chain using `magrittr`’s pipe operator, `%>%`. How can we do that? Well we can pipe our list into a `.` which acts as a placeholder for the list, on which we can perform our subset.

``````library(magrittr)
z1 %>% .[[2]]
# [1] 2.718``````

Another solution is to call `[[` using its syntactic form `[[()` using backticks (or quotes, see `?Quotes`).

``````z1 %>% `[[`(2)
# [1] 2.718``````

Admittedly, these two solutions don’t look very nice. So what we can do instead is assign the `[[` function to an object which will, in effect, be a callable wrapper function.

``````get <- .Primitive("[[") # Equivalent to get <- `[[`
get(z1, 2)
# [1] 2.718``````

Primitives are functions that are internally implemented by R and so `.Primitive("[[")` tells R to dispatch to the underlying C code, which will be able to correctly identify which `[[` method to use on the list class (see `?.Primitive` for more details).

Since our list is now the first argument of `get()`, we have a much “cleaner” looking way of accessing elements of a list with the `magrittr` pipe operator than `[[`. And so, let’s access the second element of our list using `get()` and the `magrittr` pipe.

``````z1 %>% get(2)
# [1] 2.718``````

We can also access the list using its names, too.

``````z1 %>% get("b")
# [1] 2.718``````

It even works with recursive indexing!

``````z2 <- list(a = list(b = 9, c = "hello"), d = 1:5)
z2
# \$a
# \$a\$b
# [1] 9
#
# \$a\$c
# [1] "hello"
#
#
# \$d
# [1] 1 2 3 4 5
z2 %>% get(c("a", "c")) # equivalent to z %>% get(c(1, 2))
# [1] "hello"``````

Note, you may want to choose a better name than `get` to avoid clashes with the `base::get()` function.

# Setting List Elements

Similarly we can create a `set()` function to assign values to elements of our list using `.Primitive("[[<-")`. Let’s add a fourth element to our list.

``````set <- .Primitive("[[<-")
z1 <- z1 %>% set("d", 4.6692)
z1
# \$a
# [1] 3.141593
#
# \$b
# [1] 2.718
#
# \$c
# [1] 0.57721
#
# \$d
# [1] 4.6692``````

And now just as `set()` giveth, `set()` taketh away.

``````z1 <- z1 %>% set("d", NULL)
z1
# \$a
# [1] 3.141593
#
# \$b
# [1] 2.718
#
# \$c
# [1] 0.57721``````

Of course as this is a list, we can set any kind of data.

``````z1 %>% set("data", data.frame(a = c(1, 2, 2, 4), b = c(2, 3, 7, 4)))
# \$a
# [1] 3.141593
#
# \$b
# [1] 2.718
#
# \$c
# [1] 0.57721
#
# \$data
#   a b
# 1 1 2
# 2 2 3
# 3 2 7
# 4 4 4``````

Or even overwrite elements.

``````z1 %>% set("b", 4.6692)
# \$a
# [1] 3.141593
#
# \$b
# [1] 4.6692
#
# \$c
# [1] 0.57721``````

# Conclusion

This was just a short blog post to highlight the power of `magrittr` in combination with R primitives. We also saw how to rewrite and manipulate syntactic forms of internal R functions. What other interesting use cases have you found for the `magrittr` pipe?

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.