51

I'd like to set up a list with named entries whose values are left uninitialized (I plan to add stuff to them later). How do people generally do this? I've done:

mylist.names <- c("a", "b", "c")
mylist <- as.list(rep(NA, length(mylist.names)))
names(mylist) <- mylist.names

but this seems kind of hacky. There has to be a more standard way of doing this...right?

lowndrul
  • 3,715
  • 7
  • 36
  • 54
  • Vaguely related: http://stackoverflow.com/questions/5042806/r-creating-a-named-vector-from-variables/5043280#5043280 – Andrie Apr 16 '11 at 18:37

4 Answers4

65

I would do it like this:

mylist.names <- c("a", "b", "c")
mylist <- vector("list", length(mylist.names))
names(mylist) <- mylist.names
Thilo
  • 8,827
  • 2
  • 35
  • 56
  • 27
    There is function to set names: `setNames(vector("list", length(mylist.names)), mylist.names)`. – Marek Apr 18 '11 at 11:10
  • 2
    It always depends on what you want to archive. I usually like to break up steps to make reading the code easier. R / Splus tends to let you write quite a lot of stuff in one line - which is fine for testing and getting done fast, but bad for readability. – Thilo Apr 18 '11 at 12:33
38

A little bit shorter version than Thilo :)

mylist <- sapply(mylist.names,function(x) NULL)
Wojciech Sobala
  • 7,431
  • 2
  • 21
  • 27
  • 2
    I like it. One thing to add, if your names are numbers, the numeric values are ignored as names, and just 1, 2, 3... are used. To circumvent that, try: `sapply(as.character(4:6),function(x) NULL)` – mpettis Sep 12 '13 at 15:28
  • 2
    Beware of using `sapply` inside a function https://twitter.com/hadleywickham/status/434339083871993856 – Jubbles Jan 20 '16 at 01:50
  • You can replace `sapply` with `purrr::map` using `mylist <- purrr::map(mylist.names, ~ NULL)` – psychonomics Apr 13 '17 at 07:07
  • 1
    However, you then need to use `names(mylist) <- mylist.names` – psychonomics Apr 13 '17 at 07:29
  • 1
    Best of both worlds? `lapply(mylist.names, function(x) NULL) %>% setNames(mylist.names)` – hmhensen Dec 17 '18 at 02:52
8

Another tricky way to do it:

mylist.names <- c("a", "b", "c") 

mylist <- NULL
mylist[mylist.names] <- list(NULL)

This works because your replacing non-existing entries, so they're created. The list(NULL) is unfortunately required, since NULL means REMOVE an entry:

x <- list(a=1:2, b=2:3, c=3:4)
x["a"] <- NULL # removes the "a" entry!
x["c"] <- list(NULL) # assigns NULL to "c" entry
Tommy
  • 39,997
  • 12
  • 90
  • 85
  • 2
    I would probably use `mylist <- list()` because it more clearly shows you are initializing an empty list. I actually am somewhat surprised that it works with setting it to `NULL`. I assume that `mylist` gets promoted from a `NULL` to a list when you assign to it that way. – Brian Diggs Jul 03 '14 at 22:34
0
vector("list", length(mylist.names)) |> setNames(mylist.names)
$a
NULL

$b
NULL

$c
NULL

Inspired by this comment

Julien
  • 1,613
  • 1
  • 10
  • 26