Inferrator
Inferrator

Reputation: 87

How to use purrr::map to base::assign?

How to get from meow to purr?

Let's say I have a list with 2 elements "a" and "b". I want to copy these elements into my Global environment. If I wanted to just add these elements to the search path, I'd use assign. However, I want to create a copy. And I'd like to use purrr::map to do this. How does it work?

mylist <- list(a=1:2, b=3:4)

#nope
map(mylist, assign, x=names(.), value=.)

#no
map(mylist, assign(x=names(.), value=.))

#no
map2(mylist, names(mylist), assign(x=.y, value=.x) )

#no
map2(mylist, names(mylist), assign, x=.y, value=.x )

Upvotes: 1

Views: 1040

Answers (2)

akrun
akrun

Reputation: 887511

Easier is list2env from base R applied directly on the named list to create the objects from the names in the global environment

list2env(mylist, .GlobalEnv)

Regarding the use of map, it returns only the value and not the names


A slightly related to this topic would be destructuring assignment. In R, this can be done with %<-% operator from zeallot

library(zeallot)
c(a, b) %<-% mylist

Upvotes: 3

r2evans
r2evans

Reputation: 160607

Several responses to this :-)

  1. Don't. My first visceral and emphatic response: don't do that. Very rarely do I find the use of get/assign justified, most commonly they are indications of inefficient (if not poor) data management. Having similar-structured things in a list means that you can efficiently operate on them (using map or lapply or similar).

  2. Base R does this very efficiently with list2env.

    ls()
    # character(0)
    list2env(list(a=1:2, b=3:4), envir = .GlobalEnv)
    # <environment: R_GlobalEnv>
    ls()
    # [1] "a" "b"
    
  3. If you must use purrr, then what you need is both the name and the value, so use purrr::imap:

    ls()
    # character(0)
    imap(list(a=1:2, b=3:4), ~ assign(..2, ..1, envir = .GlobalEnv))
    # $a
    # [1] 1 2
    # $b
    # [1] 3 4
    ls()
    # [1] "a" "b"
    

    The reason your assign calls failed was that it was assigning it to the then-current environment, which is neither global nor something you get to use after your call to map/map2.

Upvotes: 6

Related Questions