vestland
vestland

Reputation: 61164

How to loop through and edit certain elements of a nested list?

I'd like to reference and edit a varying number of elements in a nested list like this:

# example:
a <- list()
a$var1$var11 <- 101
a$var1$var12 <- 102
a$var2$var21 <- 201
a$var3$var31 <- 301
str(a)



# output
#List of 3
# $ var1:List of 2
#  ..$ var11: num 101
#  ..$ var12: num 102
# $ var2:List of 1
#  ..$ var21: num 201
# $ var3:List of 1
#  ..$ var31: num 301

But let's say that the list is much larger, and with a varying size everytime it's made. How can I loop through every var1, var2, check if the name is exactly var2, and then change the value in a$var2$var21 from 201 to something else?

I've tried this:

for (elem in str(a)){
  print(elem)
  if(elem==var2){
    print(elem)
  }
}

This seems to be running fine, but the output is:

List of 3
 $ var1:List of 2
  ..$ var11: num 101
  ..$ var12: num 102
 $ var2:List of 1
  ..$ var21: num 201
 $ var3:List of 1
  ..$ var31: num 301

And what I'd really like to do is using elem to subset parts of the list so that elem would replace var1 in a$var1$var11 like this a$elem$var11 and the output would be num 101

I suspect I'm approaching this thing in a wrong way, but I just don't know what different approach I should pursue. Any suggestions would be great!

Upvotes: 2

Views: 86

Answers (2)

Chuck P
Chuck P

Reputation: 3923

I'm not completely sure what you want to do with replacement logic. But thought I would offer up at least an alternate syntax you might find easier to work with from purrr

library(purrr)
# example:
a <- list()
a$var1$var11 <- 101
a$var1$var12 <- 102
a$var2$var21 <- 201
a$var3$var31 <- 301

a
#> $var1
#> $var1$var11
#> [1] 101
#> 
#> $var1$var12
#> [1] 102
#> 
#> 
#> $var2
#> $var2$var21
#> [1] 201
#> 
#> 
#> $var3
#> $var3$var31
#> [1] 301


# with pluck you can use either strings or numeric index
pluck(a, "var1", "var11")
#> [1] 101

# I think you want to iterate over every single list item?

for(elem in seq_along(a)) {
  for(subelement in seq_along(pluck(a, elem))) {
    print(pluck(a, elem, subelement))
    mytarget <- pluck(a, elem, subelement)
    if(mytarget == 201) {
      pluck(a, elem, subelement) <- 999
      cat("Replacment made\n")
    }
  }
}
#> [1] 101
#> [1] 102
#> [1] 201
#> Replacment made
#> [1] 301
a
#> $var1
#> $var1$var11
#> [1] 101
#> 
#> $var1$var12
#> [1] 102
#> 
#> 
#> $var2
#> $var2$var21
#> [1] 999
#> 
#> 
#> $var3
#> $var3$var31
#> [1] 301

Created on 2020-05-08 by the reprex package (v0.3.0)

Upvotes: 1

akrun
akrun

Reputation: 887691

We could do

for(nm in names(a)) if(nm == 'var2') a[[nm]][[1]] <- 'new'

Upvotes: 2

Related Questions