从变量创建一个命名向量

18

在函数内部,我会像这样定义一堆标量变量:

a <- 10
b <- a*100
c <- a + b

在函数的最后,我想要以命名向量的形式返回a,b,c,与变量具有相同的名称,并且要使用最少的代码,即我不想这样做:

c( a = a, b = b, c = c )

是否有一种语言结构可以实现这个功能?例如,如果我只是简单地执行return(c(a,b,c)),它会返回一个未命名的向量,这不是我想要的。我目前有一种笨拙的方法来实现这个:

> cbind(a,b,c)[1,]
   a    b    c 
  10 1000 1010 

也许还有更好的方法,不需要这么hacky(笨拙)吗?


1
c(a=a,b=b,c=c)有什么比这更不简洁的呢?你必须在某个地方指定名称和值。或者你希望它神奇地意识到'a'被称为'a'吗? - Spacedman
1
是的,那就是我想要的 - 例如上面的 cbind 就可以做到,而且它的精简性让我很满意,但我想知道是否有更直接的方法。变量名可能很长...我想节省打字的时间 :) - Prasad Chalasani
你想省略打字,但这会使你的代码变得晦涩难懂(如果我看到这样的结构,我会尽快将其从代码中删除),并且在处理大量向量时会损失相当多的性能。我真的认为你应该重新考虑一下,是否找到了可以用不同方式解决的问题的解决方案。 - Joris Meys
1
你为什么关心在函数内节省打字?你只需要写一次。我鼓励你更关注执行速度和清晰度。 - Joshua Ulrich
@Joshua 我总体上同意你的观点。我只是被 cbind() 保留变量名而 c() 不保留的事实所困扰,所以我在查看是否有简单的方法来实现这一点。 - Prasad Chalasani
1个回答

15

这是一个可以帮助您完成此操作的函数,还允许您选择性地为某些值命名。除了获取未计算表达式并将其解析成单个字符向量的技巧外,该函数并没有太多内容。

c2 <- function(...) {
  vals <- c(...)

  if (is.null(names(vals))) {
    missing_names <- rep(TRUE, length(vals))
  } else {
    missing_names <- names(vals) == ""
  }
  if (any(missing_names)) {
    names <- vapply(substitute(list(...))[-1], deparse, character(1))
    names(vals)[missing_names] <- names[missing_names]
  }

  vals
}

a <- 1
b <- 2
c <- 3

c2(a, b, d = c)
# a b d 
# 1 2 3 

请注意,无法保证生成的名称在语法上是有效的。如果您需要保证有效性,请对names向量应用make.names函数。

c2(mean(a,b,c))
# mean(a, b, c) 
#            1 

另外,与使用 substitute 函数的任何函数一样,c2 更适合于交互式使用,而不适合在另一个函数内部使用。


@hadley: substitute(list(...))[-1] 可以简化为 substitute(...()) - Tommy
2
缩短了,但更加混乱!(我意识到列表没有被使用,但它传达了意图) - hadley
1
@hadley:我已经将两个函数ncnlist添加到我的kimisc,并在其中给予了您和这个答案的认可。 - krlmlr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接