我知道列表中的NULL值有时可能会trip人。我很好奇为什么在特定实例中lapply
和rapply
似乎对NULL
值的处理方式不同。
l <- list(a = 1, c = NULL, d = 3)
lapply(l,is.null)
$a
[1] FALSE
$c
[1] TRUE
$d
[1] FALSE
到目前为止一切顺利。如果我们使用rapply
执行完全相同的操作怎么样?
rapply(l, is.null, how = "replace")
$a
[1] FALSE
$c
list()
$d
[1] FALSE
此示例非常简单且非递归,但您在rapply
中看到了与嵌套列表相同的行为。
我的问题是为什么?如果像?rapply
中所宣传的那样,它是“lapply的递归版本”,为什么它们在这种情况下表现得如此不同?
答案 0 :(得分:20)
我认为你回答了自己的问题:因为它是递归的。
您通常不会看到这一点,但NULL
实际上可用于指示空序列,因为它是空的pairlist
(类似于Scheme中()
的终止方式列表。在内部,R非常类似于计划。
所以,rapply
递归到空列表中,但是当它完成时,它不会把它变回一个pairlist;你得到一个常规的空列表。
实际上,rapply
和lapply
并没有真正区别对待NULL:
> lapply(NULL, identity)
list()
你可以在R源代码(memory.c)中看到,这正是pairlists的工作方式:
SEXP allocList(int n)
{
int i;
SEXP result;
result = R_NilValue;
for (i = 0; i < n; i++)
result = CONS(R_NilValue, result);
return result;
}