【发布时间】:2015-06-10 06:36:51
【问题描述】:
从数据库游标读取记录时,通常事先不知道有多少行即将出现。这使得不可能预先分配正确大小的列表来存储这些对象。
当总大小未知时,将所有记录存储在列表中的有效方法是什么?基本列表类型很慢,因为每次添加元素时它都会复制整个列表:
x <- list()
for(i in 1:1e5){
x[[i]] <- list("foo" = rnorm(3), bar = TRUE)
}
环境效率更高,但它是一个映射而不是有序集合。所以我们需要将索引转换为字符串,然后对键进行排序以检索值,这似乎不是最理想的:
env <- new.env()
for(i in 1:1e5){
env[[sprintf("%09d", i)]] <- list("foo" = rnorm(3), bar = TRUE)
}
x <- lapply(sort(ls(env)), get, env, inherits = FALSE)
pairlist 应该是 R 中的链表,但是只要从 R 中附加一个元素,R 似乎就会将其强制转换为常规列表。
【问题讨论】:
-
哪里说
pairlist是一个链表?我认为这不太可能,因为它的性能特征(根据快速microbenchmark测试,索引访问几乎肯定是恒定的,不是线性的)。 [文档中提到了“点对列表”,但这可能只是指pairlist设计的起源,而不是具体的实现。] -
把它们放在一个环境中怎么样?这本质上是一个(散列)字典。您可以只为记录编号并在环境中调用它们
1、2等。这应该很快。然后最后转换成列表。 -
那是在帖子中描述的。但是以正确的顺序对键进行排序和提取值的效率有点低。
-
@KonradRudolph,pairlist (
LISTSXP) 确实是一个链表。有关 R 如何将它们用于解析器的示例,请参阅 github.com/wch/r-source/blob/trunk/src/main/gram.y#L1055-L1104。 -
@Jeroen 是的,很抱歉没有阅读这个问题! :( 您实际上可以更快地将环境转换为(排序的)列表,请参阅我的答案。
标签: r