R中的列表与pairlist有什么区别?

Chr*_*oms 33 r list

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

Bro*_*ieG 22

天天轮回的R

有两个地方,对列表将在日常R中常见.一个是函数形式:

str(formals(var))
Run Code Online (Sandbox Code Playgroud)

另一个是语言对象.例如:

quote(1 + 1)
Run Code Online (Sandbox Code Playgroud)

产生一种语言类型的pairlist(LANGSXP内部).您甚至关心意识到这一点的主要原因是由于内部存储了如何旋转的操作,例如length(<language object>)或者language_object[[x]]可能会很慢(尽管长的旋转语言对象有点罕见;注释表达式不是pairlist).

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

list(x=substitute(x, alist(x=)))  # hack alert
Run Code Online (Sandbox Code Playgroud)

所有这一切,在大多数情况下,OP是正确的,除非你正在编写用于R的C代码,否则你不必过多担心pairlists.

列表和pairlists之间的内部差异

Pairlists和list主要在它们的存储结构中不同.Pairlists存储为节点链,除了节点的内容和节点的"名称"之外,每个节点都指向下一个节点的位置(有关一般性讨论,请参阅CAR/CDR wiki文章).除此之外,这意味着您无法知道pairlist中有多少元素,除非您知道哪个元素是第一个元素,然后您遍历整个列表.

Pairlists广泛用于R内部,并且确实存在于正常的R使用中,但大多数时候都是通过打印或访问方法伪装和/或在访问时强制列表.

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

骑行者的好处

pairlists的一个(通常很小的)好处是你可以以最小的开销添加它们,因为你只需要修改最多两个节点(新节点前面的节点和新节点本身),而你可能需要一个列表通过增加大小来重新分配整个地址表(这通常不是问题,因为地址表通常与表指向的数据大小相比非常小).还有许多算法专门用于pairlist操作(例如排序,索引等),但这些算法也可以移植到普通列表中.

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

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

有关详细信息,请参阅R Internals(分别在链接位置查找LISTSXP和VECSXP,pairlists和列表).

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

> 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
Run Code Online (Sandbox Code Playgroud)


Chr*_*oms 18

首先,pairlists被弃用了

pairlists因正常使用而被弃用.除非你正在研究R internals,否则你不需要担心它们.


列表可以包含命名元素

R中列表中的每个元素都可以有一个名称.您可以按名称或其数字索引访问列表中的每个元素.

以下是第二个元素名为"second"的列表示例:

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

$second
[1] "B"

[[3]]
[1] "C"
Run Code Online (Sandbox Code Playgroud)

所有元素都可以通过其在列表中的位置来编制索引.还可以通过名称访问命名元素:

> my.list[[2]]
[1] "B"
> my.list$second
[1] "B"
Run Code Online (Sandbox Code Playgroud)

此外,列表中的每个元素都是一个向量,即使它只是一个包含单个元素的向量.有关列表的更多信息,请参阅如何在R中正确使用列表?.


pairlists可以包含空的命名元素

pairlist基本上与列表相同,除了pairlist可以包含空的命名元素,但列表不能.此外,使用该alist功能构建了一个pairlist .

> 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"
Run Code Online (Sandbox Code Playgroud)

但是,如前所述,它们已被弃用.与我所知的列表相比,它们没有任何好处或优势.