Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a consistent vector of list element names

Tags:

r

A list with no names returns NULL for its names:

> names(list(1,2,3))
NULL

but add one named thing and suddenly the names has the length of the list:

> names(list(1,2,3,a=4))
[1] ""  ""  ""  "a"

because this is now a named list. What I'd like is a function, rnames say, to make any list into a named list, such that:

rnames(list(1,2,3)) == c("","","")
identical(rnames(list()), character(0))
length(rnames(foo)) == length(foo) # for all foo

and the following, which is what names() does anyway:

rnames(list(1,2,3,a=3)) == c("","","","a")
rnames(list(a=1,b=1)) == c("a","b")

My current hacky method is to add a named thing to the list, get the names, and then chop it off:

rnames = function(l){names(c(monkey=1,l))[-1]}

but is there a better/proper way to do this?

like image 892
Spacedman Avatar asked Dec 08 '11 16:12

Spacedman


2 Answers

An approach that feels slightly cleaner is to assign names to the list:

x <- list(1,2,3)
names(x) <- rep("", length(x))
names(x)
[1] "" "" ""

Turning it into a function:

rnames <- function(x){
  if(is.null(names(x))) names(x) <- rep("", length(x))
  return(x)
}

Test cases:

x1 <- rnames(list(1,2,3))
x2 <- rnames(list(1,2,3,a=3))
x3 <- rnames(list(a=1,b=1))

names(x1)
[1] "" "" ""

names(x2)
[1] ""  ""  ""  "a"

names(x3)
[1] "a" "b"
like image 159
Andrie Avatar answered Oct 21 '22 23:10

Andrie


How about something like this?

rnames <- function(x) {
    if(is.null(names(x)))
      character(length(x))
    else
      names(x)
}

It handles the list() and no names cases; and it doesn't do anything if there are already names.

like image 22
Joshua Ulrich Avatar answered Oct 21 '22 23:10

Joshua Ulrich