Constructing a Named List Without Having to Type Each Object's Name Twice

Can lists be created that name themselves based on input object names?

Coincidentally, I just wrote this function. It looks a lot like @joran's solution, but it tries not to stomp on already-named arguments.

namedList <- function(...) {
L <- list(...)
snm <- sapply(substitute(list(...)),deparse)[-1]
if (is.null(nm <- names(L))) nm <- snm
if (any(nonames <- nm=="")) nm[nonames] <- snm[nonames]
setNames(L,nm)
}
## TESTING:
a <- b <- c <- 1
namedList(a,b,c)
namedList(a,b,d=c)
namedList(e=a,f=b,d=c)

Copied from comments: if you want something from a CRAN package, you can use Hmisc::llist:

Hmisc::llist(a, b, c, d=a, labels = FALSE)

The only apparent difference is that the individual vectors also have names in this case.

Creating unique object names for list entries

Maybe there is a more elegant way but just going through the list and renaming items while keeping count of each name's uses works fine:

# all used names
names.used <- unique(unlist(sapply(listoflists, names)))
# usage counter for each name
names.n <- setNames(rep(0, length(names.used)), names.used)

for (i in seq_along(listoflists)) {
for (j in seq_along(listoflists[[i]])) {

name.ij <- names(listoflists[[i]])[j]

# rename second and further occurrences
if (names.n[name.ij] > 0) {
names(listoflists[[i]])[j] <- paste0(name.ij, names.n[name.ij])
}

# update counter
names.n[name.ij] <- names.n[name.ij] + 1
}
}
# [[1]]
# [[1]]$a
# [1] "1" "a" "3" "4"
#
# [[1]]$b
# [1] "5" "b" "6" "7"
#
#
# [[2]]
# [[2]]$a1
# [1] "1" "a" "2" "6"
#
# [[2]]$b1
# [1] "5" "b" "0" "8"
#
#
# [[3]]
# [[3]]$d
# [1] "1" "a" "2" "6"
#
# [[3]]$b2
# [1] "5" "b" "0" "8"
#
#
# [[4]]
# [[4]]$d1
# [1] "1" "a" "2" "3"
#
# [[4]]$b3
# [1] "5" "b" "0" "8"
#
# [[4]]$a2
# [1] "5" "b" "0" "8"
#
#
# [[5]]
# [[5]]$d2
# [1] "1" "a" "1" "1"

Why do we have to type the class name twice when instantiating a new object in Java?

On the left hand:

ClassName instancename

The ClassName is declaring type (= class) of variable instancename.

On the right hand:

new ClassName();

The ClassName() is invoking a (constructor) method named ClassName().

So, you are doing two things at once.

ClassName instancename;         // declaring type
instancename = new ClassName(); // invoking method

Your example:

ClassName instancename = new ClassName();

is just shortened style of the two instructions.

There are other styles of getting an instance of a class -- newInstance() or getInstance() for example.

That is: declaration of type and method of instantiation are the separate things. They are needed for their own purposes.

Give name to list variable

Since @akrun doesn't need any more points, here is an example showing how you can assign names to a list:

lst <- list(a="one", b="two", c=c(1:3))
names(lst)
[1] "a" "b" "c"
names(lst) <- c("x", "y", "z")

> lst
$x
[1] "one"

$y
[1] "two"

$z
[1] 1 2 3

Return a named list with various elements from function call

  1. mget Use mget as shown below. To return all variables use mget(ls()) or to return all variables except x use mget(setdiff(ls(), "x")). ls will not return object names that begin with a dot unless the all argument is used, i.e. ls(all = TRUE), which could be used to prevent certain variables from being returned. Another possibility is to use the mode= argument of mget to restrict the objects returned to ones that are numeric, say. See ?mget. Yet another approach to restrict the objects returned is to use Filter on the result of mget. For example, res <- Filter(is.data.frame, mget(ls())) only returns data frames.

    myfunc <- function(x){
    a1 = 1
    a2 = c(2,4)
    a3 = data.frame(x = 1:10)
    an = 'str'
    res = mget(ls(pattern = "^a"))
    return(res)
    }
    myfunc(3) # test
  2. environment Another possibility is to return the environment within the executing function. All objects in the function (not just the ones beginning with a) will be in the environment.

    myfunc2 <- function(x) {
    a1 = 1
    a2 = c(2,4)
    a3 = data.frame(x = 1:10)
    an = 'str'
    res = environment()
    return(res)
    }
    out <- myfunc2(3) # test
    out$a
  3. within Another possibility is to use within. Only variables created in the within will be returned. x is used in the within but not created in the within so it is not returned.

    myfunc3 <- function(x) {
    res <- within(list(), {
    a1 <- x
    a2 <- BOD
    })
    return(res)
    }
    myfunc3(3) # test
  4. Multiple ls Perform an ls() before and after the section creating the variables to be output and then mget the difference.

    myfunc4 <- function(x) {
    .excl <- ls()
    a1 <- x
    a2 <- BOD
    res <- mget(setdiff(ls(), .excl))
    return(res)
    }
    myfunc4(3) # test

From a list of objects, get a character vector of their names

Once you run

tests <- list(mean, varience, skewness, kurtosis)

those symbols are evaluated and discarded. If you look at

tests[[2]]

or something, you can see there really isn't an original reference to varience, but rather the funcion that the symbol varience pointed to is now stored in a list. (Things work a bit differently when passing parameters to functions thanks to the promises and the call stack but that's not what you're doing here). There is no lazy-evaluation for list() after you've run it.

If you want to keep the names of the functions, it's probably best to work with a named list. You can make a helper function like

nlist <- function(...) { dots<-substitute(...()); setNames(list(...), sapply(dots, deparse))}
tests <- nlist(mean, var, skewness, kurtosis)

Now the values are preserved as names

names(tests)
# [1] "mean" "var" "skewness" "kurtosis"


Related Topics



Leave a reply



Submit