Reputation: 1365
I have list of lists that are all the same structure and I want to alter one element of each of the lists in the second tier. In other words, I have a single list with objects x, y & z. This list is repeated multiple times in another list. I need to change x in each of these lists. What is the best way to do this?
My current approach is to create a small function that does the change I want and then re-create the list. But there is something that makes me think that there is simpler way to do this?
The code below shows my approach, which is fine for my toy example - but the real context the object is more complicated, so I don't really want to have to recreate it multiple times considering I only change one value. I could do it this way, it just feels convoluted.
l = list(x = 1:3, y = "a", z = 9)
test = list(l, l, l)
standardize = function(obj){
obj$x = obj$x / max(obj$x)
list(obj$x, obj$y, obj$z)
}
lapply(test, function(e) standardize(e))
Upvotes: 4
Views: 1493
Reputation: 17369
Seeing as the size of your list is already fixed, this is a situation where a simple for
loop is also quite suitable for the task.
for(i in seq_along(test)){
test[[i]]$x <- test[[i]]$x / max(test[[i]]$x)
}
I clock this as being a mere 0.8 milliseconds slower than the lapply
solution.
Upvotes: 0
Reputation: 43334
With purrr:
library(purrr)
test2 <- test %>% map(map_at, 'x', ~.x / max(.x))
or
test2 <- test %>% map(update_list, x = ~x / max(x))
Either way, you get
str(test2)
## List of 3
## $ :List of 3
## ..$ x: num [1:3] 0.333 0.667 1
## ..$ y: chr "a"
## ..$ z: num 9
## $ :List of 3
## ..$ x: num [1:3] 0.333 0.667 1
## ..$ y: chr "a"
## ..$ z: num 9
## $ :List of 3
## ..$ x: num [1:3] 0.333 0.667 1
## ..$ y: chr "a"
## ..$ z: num 9
Upvotes: 3
Reputation: 6921
Simply return the modified obj
instead of re-creating a list.
standardize = function(obj){
obj$x <- obj$x / max(obj$x)
obj
}
Bonus: the names of obj's elements are now preserved.
Upvotes: 5