R中的列表和成对列表有什么区别?

R中的列表和成对列表有什么区别?,r,list,R,List,在阅读列表文档时,我发现了对pairlist的引用,但我不清楚它们与列表的区别。首先,pairlist是不推荐的 成对列表是因为“通用向量”通常更有效。除非您正在研究R的内部结构,否则您永远不需要担心它们 列表可以包含命名元素 R中列表中的每个元素都可以有一个名称。您可以通过名称或其数字索引访问列表中的每个元素 下面是第二个元素名为“second”的列表示例: > my.list <- list('A',second='B','C') > my.list [[1]] [1]

在阅读列表文档时,我发现了对pairlist的引用,但我不清楚它们与列表的区别。

首先,pairlist是不推荐的 成对列表是因为“通用向量”通常更有效。除非您正在研究R的内部结构,否则您永远不需要担心它们


列表可以包含命名元素 R中列表中的每个元素都可以有一个名称。您可以通过名称或其数字索引访问列表中的每个元素

下面是第二个元素名为“second”的列表示例:

> my.list <- list('A',second='B','C')
> my.list
[[1]]
[1] "A"

$second
[1] "B"

[[3]]
[1] "C"
此外,列表中的每个元素都是一个向量,即使它只是一个包含单个元素的向量。有关列表的详细信息,请参阅


成对列表可以包含空的命名元素 pairlist与list基本相同,只是pairlist可以包含一个空的命名元素,而list不能。此外,使用
alist
函数构造成对列表

> list('A',second=,'C')
Error in as.pairlist(list(...)) : argument is missing, with no default
> alist('A',second=,'C')
[[1]]
[1] "A"

$second


[[3]]
[1] "C"
但是,如前所述,它们已被弃用。与我所知道的列表相比,它们没有任何好处或优势。

day-to-day R中的成对列表 日常R中通常会出现两个位置的配对列表。一个是函数形式:

str(formals(var))
二是作为语言对象。例如:

quote(1 + 1)
生成类型为language(内部为LANGSXP)的成对列表。您甚至需要注意这一点的主要原因是,诸如
length()
language\u object[[x]]]
之类的操作可能会很慢,因为pairlist是如何在内部存储的(尽管长pairlist语言对象有点罕见;注意表达式不是pairlist)

请注意,空元素只是零长度的符号,如果您有点作弊,您实际上可以将它们存储在列表中(尽管您可能不应该这样做):

尽管如此,在大多数情况下,OP是正确的,您不需要过多地担心pairlist,除非您正在编写用于R的C代码

列表和成对列表之间的内部差异 成对列表和列表的主要区别在于它们的存储结构。成对列表存储为一个节点链,其中每个节点除了指向节点的内容和节点的“名称”外,还指向下一个节点的位置(请参见)。除此之外,这意味着您无法知道成对列表中有多少个元素,除非您知道第一个元素是什么,然后遍历整个列表

PairList在R内部广泛使用,在正常的R使用中确实存在,但大多数情况下被打印或访问方法所掩盖,和/或在访问时被强制为列表

列表也是地址列表,但与成对列表不同,所有地址都存储在一个连续的内存位置,并跟踪总长度。这使得按位置访问列表中的任意成员变得很容易,因为您只需在内存表中查找地址即可。使用成对列表,您必须从一个节点跳到另一个节点,直到最终到达所需的节点。名称也存储为列表本身的属性,而不是附加到成对列表的每个节点

成对主义者的好处 PairList的一个(通常很小)好处是,您可以以最小的开销添加到它们中,因为您最多只需要修改两个节点(新节点之前的节点和新节点本身),而对于列表,您可能需要随着大小的增加重新分配整个地址表(这通常不是什么大问题,因为与表所指向的数据大小相比,地址表通常非常小)。也有许多算法专门用于成对列表操作(例如排序、索引等),但这些算法也可以移植到普通列表

由于您只能在内部执行此操作,所以与日常使用不太相关,通过更改任意元素指向的对象,从编程角度修改列表非常容易

与上述内容松散相关的是,当您拥有高度嵌套的对象时,成对列表可能会更有效。列表可以轻松复制此结构,但每个列表和嵌套列表都会有额外的内存地址表。这可能是成对列表用于极有可能具有高度嵌套/元素的语言对象的原因比率

有关更多详细信息,请参见(在链接位置分别查找LISTSXP和VECSXP、成对列表和列表)

编辑:有趣的是,将列表的内存占用与成对列表进行比较的实验表明,成对列表更大,因此存储效率参数可能不正确(不确定此处是否可以信任
object.size
):

>plist\u to\u列出y对象。大小(y)
4656字节

这里有一些奇怪的事情:虽然标准列表不能容纳空元素,但它可以容纳
bquote()
作为元素。对于为未指定维数的数组编写函数,使用
do.call(“[”,c(list(arr),…)”)
非常有用,您可能希望参数列表包含
bquote()
。我想
bquote()
基本上允许
list
list
所能做的一切。知道为什么一个pairlist被称为pairlist吗?与其使用
bquote()
不如使用
substitute()
我认为它可能被称为pairlist,因为它的大小(三个元素)有限,对于您拥有的语言对象和运算符元素(第一个),然后是一对参数(第二个、第三个参数)。我投了反对票,请提供一份反对使用成对列表的参考资料,然后我会将其转换为upvote。我在手册中没有找到任何信息。对于高度嵌套的结构,或者对语言对象进行操作的元编程,这似乎仍然是合理的。@jangorecki我添加了您请求的链接。
quote(1 + 1)
list(x=substitute(x, alist(x=)))  # hack alert
> plist_to_list <- function(x) {
+   if(is.call(x)) x <- as.list(x)
+   if(length(x) > 1) for(i in 2:length(x)) x[[i]] <- Recall(x[[i]])
+   x
+ }
> add_quote <- function(x, y) call("+", x, y)
> x <- Reduce(add_quote, lapply(letters, as.name))
> object.size(x)
7056 bytes
> y <- plist_to_list(x)
> object.size(y)
4656 bytes