thothal
thothal

Reputation: 20399

Mutate logic for lists

I want to add elements to a list using existing slots of this very list. In base R I would use the following syntax:

l <- list(a = 1, b = 2, e = 1, f = 1)
## Add slot c and d  which take the values from a and b respectively
l$c <- l$a
l$d <- l$b
str(l)
# List of 6
#  $ a: num 1
#  $ b: num 2
#  $ e: num 1
#  $ f: num 1
#  $ c: num 1
#  $ d: num 2

Avoiding l$ can be done via attach / with / within which I do not want to use.

So what is the canonical way of doing that with tidyverse? One solution I could think of is:

library(magrittr)
library(purrr)
l <- list(a = 1, b = 2, e = 1, f = 1)
str(l %$% list_modify(l, c = a, d = b))
str(l)
# List of 6
#  $ a: num 1
#  $ b: num 2
#  $ e: num 1
#  $ f: num 1
#  $ c: num 1
#  $ d: num 2

But as there are plenty of functions in the tidyverse I was wondering whether there is afunction which is "more" fit for purpose, i.e. using maybe less different libraries / function calls?


Update. Adapted the example slightly to highlight that not all columns will be copied.

Upvotes: 2

Views: 63

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 389175

Not a tidy way but you can do :

append_list <- function(l, copy_from, copy_to) {
  if(length(copy_from) != length(copy_to)) 
    stop('length of copy_from and copy_to should be equal')
  l[copy_to] <- l[copy_from]
  l
}

append_list(l, c('a', 'b'), c('c', 'd'))

#$a
#[1] 1

#$b
#[1] 2

#$e
#[1] 1

#$f
#[1] 1

#$c
#[1] 1

#$d
#[1] 2
append_list(l, c('a', 'b'), c('c', 'd', 'e'))

Error in append_list(l, c("a", "b"), c("c", "d", "e")) : length of copy_from and copy_to should be equal

Upvotes: 2

det
det

Reputation: 5232

You can do something like:

c(l, setNames(l, c("c", "d")))

edit

Without checking if elements exist in list or if name is already taken (although list can have same names):

copy_ele <- c("a", "b")
new_names <- c("c", "d")
c(l, setNames(l[copy_ele], new_names))

Upvotes: 1

Related Questions