Removing multiple named list components inside ()

I am trying to remove a named component from the list using within and rm . This works for one component, but not for two or more. I am completely fooled.

For example, it works.

 aa = list(a = 1:3, b = 2:5, cc = 1:5) within(aa, {rm(a)}) 

output from within will only have components not removed.

However, it is not:

 aa = list(a = 1:3, b = 2:5, cc = 1:5) within(aa, {rm(a); rm(b)}) 

Also this:

 within(aa, {rm(a, b)}) 

The output from within will contain all components, with those that I am trying to remove, set to NULL . Why?

+5
source share
1 answer

First, pay attention to the following behavior:

 > 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 

Now look at the code for 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 } 

Look, in particular, at the second in the last line of the function. If the number of deleted items in the list is greater than one, the function essentially calls aa[c('a', 'b')] <- list(NULL, NULL) , because vector("list", 2) creates a list of two items, each element of which is NULL . We can create our own version of within , where we remove the else from the second to the last line of the function:

 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 } 

Now let's test it:

 > aa = list(a = 1:3, b = 2:5, cc = 1:5) > > mywithin(aa, rm(a, b)) # $cc # [1] 1 2 3 4 5 

Now it works as expected!

+4
source

Source: https://habr.com/ru/post/1236834/


All Articles