mar*_*tin 5 null r list with-statement named
我试图从列表中删除命名组件,使用within和rm.这适用于单个组件,但不适用于两个或更多组件.我完全糊涂了.
例如 - 这是有效的
aa = list(a = 1:3, b = 2:5, cc = 1:5)
within(aa, {rm(a)})
Run Code Online (Sandbox Code Playgroud)
输出within将只包含未删除的组件.
但是,这不是:
aa = list(a = 1:3, b = 2:5, cc = 1:5)
within(aa, {rm(a); rm(b)})
Run Code Online (Sandbox Code Playgroud)
这也不是:
within(aa, {rm(a, b)})
Run Code Online (Sandbox Code Playgroud)
输出within将包含所有组件,以及我要删除的组件,设置为NULL.为什么?
首先,请注意以下行为:
> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> aa[c('a', 'b')] <- NULL
>
> aa
# $cc
# [1] 1 2 3 4 5
> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> aa[c('a', 'b')] <- list(NULL, NULL)
>
> aa
# $a
# NULL
#
# $b
# NULL
#
# $cc
# [1] 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)
现在让我们看一下代码within.list:
within.list <- function (data, expr, ...)
{
parent <- parent.frame()
e <- evalq(environment(), data, parent)
eval(substitute(expr), e)
l <- as.list(e)
l <- l[!sapply(l, is.null)]
nD <- length(del <- setdiff(names(data), (nl <- names(l))))
data[nl] <- l
if (nD)
data[del] <- if (nD == 1) NULL else vector("list", nD)
data
}
Run Code Online (Sandbox Code Playgroud)
特别查看该函数的倒数第二行。如果列表中已删除项目的数量大于 1,则该函数本质上是调用aa[c('a', 'b')] <- list(NULL, NULL),因为vector("list", 2)创建一个包含两项的列表,其中每个项目都是NULL。我们可以创建自己的版本,从函数的第二行到最后一行within删除语句:else
mywithin <- function (data, expr, ...)
{
parent <- parent.frame()
e <- evalq(environment(), data, parent)
eval(substitute(expr), e)
l <- as.list(e)
l <- l[!sapply(l, is.null)]
nD <- length(del <- setdiff(names(data), (nl <- names(l))))
data[nl] <- l
if (nD) data[del] <- NULL
data
}
Run Code Online (Sandbox Code Playgroud)
现在我们来测试一下:
> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> mywithin(aa, rm(a, b))
# $cc
# [1] 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)
现在它按预期工作了!