循环'...'的最有效方式

时间:2014-02-11 08:42:30

标签: r

我在R中开发一个包,主要接口是两个类:一个处理数据的类(让我们称之为Data)和一个处理Data实例集合的类(我们称之为Collection)。数据实例可能相当大(50 mb +),这就是Collection类是环境包装的原因。

我想为Data实现一个c()函数,这将导致一个Collection实例。为了做到这一点,参数将作为...传递,并且必须迭代地构建Collection实例。我知道我可以首先通过...将其列为一个列表来遍历list(...),但这可能会非常昂贵。无论如何在没有先将所有内容复制到临时列表的情况下循环遍历...

1 个答案:

答案 0 :(得分:2)

似乎有用的是使用pryr package中的dots函数(我可以想象还有其他更简单的解决方案):

library(pryr)

fun1 <- function(...) {
  l <- dots(...)
  result <- list(mode="list", length = length(l))
  for (i in seq_along(l)) {
    v <- l[[i]]
    result[[i]] <- eval(v)
  }
   result
}

使用list和不带...的实现

实现此操作
fun2 <- function(...) {
  l <- list(...)
  result <- list(mode="list", length = length(l))
  for (i in seq_along(l)) {
    v <- l[[i]]
    result[[i]] <- v
  }
  result
}

fun1 <- function(...) {
  l <- dots(...)
  result <- list(mode="list", length = length(l))
  for (i in seq_along(l)) {
    v <- l[[i]]
    result[[i]] <- eval(v)
  }
  result
}

fun3 <- function(a, b) {
  list(a, b)
}

> system.time(r1 <- fun1(large_object1, large_object2))
   user  system elapsed 
  0.060   0.072   0.133 
> system.time(r2 <- fun2(large_object1, large_object2))
   user  system elapsed 
  0.132   0.132   0.265 
> system.time(r3 <- fun3(large_object1, large_object2))
   user  system elapsed 
  0.056   0.076   0.132 

我们发现使用dots的实现与没有...的实现类似,并且比使用list的实现更快。

如果您不想依赖pryrdots的代码非常“简单”:

dots <- function (...) {
  eval(substitute(alist(...)))
}