41

I've been doing some work with some large, complex lists lately and I've seen some behaviour which was surprising (to me, at least), mainly to do with assigning names to a list. A simple example:

Fil <- list(
a = list(A=seq(1, 5, 1), B=rnorm(5), C=runif(5)), 
b = list(A="Cat", B=c("Dog", "Bird"), C=list("Squirrel", "Cheetah", "Lion")),
c = list(A=rep(TRUE, 5), B=rep(FALSE, 5), C=rep(NA, 5)))

filList <- list()

for(i in 1:3){
  filList[i] <- Fil[i]
  names(filList)[i] <- names(Fil[i])
}
identical(Fil,filList)
[1] TRUE

but:

for(i in 1:3){
  filList[i] <- Fil[i]
  names(filList[i]) <- names(Fil[i])
}
identical(Fil,filList)
[1] FALSE

I think the main reason it confuses me is because the form of the left-hand side of first names line in the first for loop needs to be different from that of the right-hand side to work; I would have thought that these should be the same. Could anybody please explain this to me?

RobertMyles
  • 2,673
  • 3
  • 30
  • 45
  • 3
    I think of it like this, although the details are likely incorrect: when you run `names(filList[1])` you're essentially creating a new one element list within the environment created by the `names` function. Then you assign the new name, the function finishes running and your new list object is destroyed. However, when you run `names(filList)[1]` you are modifying the names of the `filList` object that exists in your global environment. – dayne Jul 28 '16 at 17:38
  • 3
    Btw, you can use the same form on both sides, like `names(x)[1] = names(y)[1]` – Frank Jul 28 '16 at 17:39
  • Thanks, dayne and Frank, for the explanations. – RobertMyles Jul 28 '16 at 17:48

1 Answers1

62

The first case is the correct usage. In the second case you are sending filList[i] to names<- which is only exists as a temporary subsetted object.

Alternatively, you could just do everything outside the loop with:

names(filList) <- names(Fil)
James
  • 65,548
  • 14
  • 155
  • 193