Update global nested list variable in function irrespective of depth

Viewed 86

I am attempting to create a function that can update selected values in a global environment variable. To complicate things, these values are located in nested lists, and the depth of the location can vary.

Here is one example:

L <- list()

L$Foo <- list()
L$Foo$Bar <- list()
L$Foo$Bar$VAR <- TRUE

L$Lorem <- list()
L$Lorem$Ipsum <- list()
L$Lorem$Ipsum$Dolor <- list()
L$Lorem$Ipsum$Dolor$VAR <- TRUE

I am trying to update L$Foo$Bar$VAR <- TRUE to L$Foo$Bar$VAR <- FALSE and L$Lorem$Ipsum$Dolor$VAR <- TRUE to L$Lorem$Ipsum$Dolor$VAR <- FALSE. As you see, the variable name inside the nested list, VAR, is the same across all variables I want to update.

Hence, I'm seeking out a function that can update all VAR variables inside a nested list, regardless of how deep VAR is.

EDIT VAR will be updated with the same value.

1 Answers

1) rrapply rrapply in package rrapply will walk L and for each element satisfying the condition defined by the second argument it will run the third argument replacing the value with that argument's output.

library(rrapply)

L2 <- rrapply(L, function(x, .xname) .xname == "VAR", function(x) FALSE)
str(L2)

giving:

List of 2
 $ Foo  :List of 1
  ..$ Bar:List of 1
  .. ..$ VAR: logi FALSE
 $ Lorem:List of 1
  ..$ Ipsum:List of 1
  .. ..$ Dolor:List of 1
  .. .. ..$ VAR: logi FALSE

2) rapply If it were known that the VAR components are the only logical components (which in the question's example is the case) then rapply in the base of R could be used.

rapply(L, function(x) FALSE, classes = "logical", how = "replace")

3) base R Using only base R we can recursively walk the tree looking for the indicated name and replacing its value with FALSE.

replace_name <- function(x, name, value) {
  if (is.list(x)) {
    Map(function(nm) 
      if (nm == name) value else replace_name(x[[nm]], name, value), names(x)
    )
  } else x
}

replace_name(L, "VAR", FALSE)

Global Environment

If we have computed L2 by one of the above means within a function and want to replace L in the global environment with it as a side effect of the function then we can use any of these:

.GlobalEnv$L <- L2

 L <<- L2

 assign("L", L2, .GlobalEnv)

Normally R functions don't operate through side effects so if you can arrange just to return it that would be even better.

Related