Удаление нескольких именованных компонентов списка в пределах ()
Я пытаюсь удалить именованный компонент из списка, используя within
а также rm
, Это работает для одного компонента, но не для двух или более. Я совершенно сбит с толку.
Например - это работает
aa = list(a = 1:3, b = 2:5, cc = 1:5)
within(aa, {rm(a)})
выход из within
будет иметь только не удаленные компоненты.
Однако это не так:
aa = list(a = 1:3, b = 2:5, cc = 1:5)
within(aa, {rm(a); rm(b)})
Ни один не делает это:
within(aa, {rm(a, b)})
Выход из within
будет иметь все компоненты, с теми, которые я пытаюсь удалить, установите в NULL
, Зачем?
1 ответ
Во-первых, обратите внимание на следующее поведение:
> 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
Теперь давайте посмотрим на код для 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
}
В частности, посмотрите на последнюю строку функции. Если количество удаленных элементов в списке больше единицы, функция по сути вызывает 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
}
Теперь давайте проверим это:
> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> mywithin(aa, rm(a, b))
# $cc
# [1] 1 2 3 4 5
Теперь все работает как положено!