Reputation: 309
[[1]]
[[1]][[1]]
[1] 1 46 107 69 1
[[1]][[2]]
[1] 1 146 145 71 92 1
####################
[[2]]
[[2]][[1]]
[1] 1 46 18 92 1
[[2]][[2]]
[1] 1 127 145 53 168 1
Assume I have 2 nested list, as shown above, I'm looking for function where I can update (say 46) in both the list with some other number in list (say 92) and update 92's with 46 without altering the structure of the list
Expected output will be something like this
[[1]]
[[1]][[1]]
[1] 1 92 107 69 1
[[1]][[2]]
[1] 1 146 145 71 46 1
####
[[2]]
[[2]][[1]]
[1] 1 92 18 46 1
[[2]][[2]]
[1] 1 127 145 53 168 1
Rlist library has functions like list.find/list.findi which works only for named nested list. Mine is not a named list
Upvotes: 3
Views: 225
Reputation: 12937
This is another way to achieve that. First you simply convert your list to vector (unlist(l)
). Do your necessary swaps and convert it back to your list (relist(x, skeleton = l)
).
x <- unlist(l)
a <- which(x==46)
b <- which(x==92)
x[a] <- 92
x[b] <- 46
relist(x, skeleton = l)
Benchmarking
library(microbenchmark)
l <- list(list(c(1, 46, 107, 69, 1), c(1, 146, 145, 71, 92, 1)), list(
c(1, 46, 18, 92, 1), c(1, 127, 145, 53, 168, 1)))
f_m0h3n <- function(l){x <- unlist(l);a <- which(x==46);b <- which(x==92);x[a] <- 92;x[b] <- 46;relist(x, l);}
f_jakub <- function(li) rapply(li, function(x) ifelse(x == 46, 92,ifelse(x==92, 46, x)), how = "list")
all.equal(f_m0h3n(l), f_jakub(l))
# [1] TRUE
microbenchmark(f_m0h3n(l), f_jakub(l))
# Unit: microseconds
# expr min lq mean median uq max neval
# f_m0h3n(l) 100.942 103.509 109.7108 107.3580 111.6355 204.879 100
# f_jakub(l) 126.178 131.738 142.8850 137.9405 143.7150 357.148 100
Larger scale
library(microbenchmark)
set.seed(123)
l <- list(list(sample(1000), sample(2000)),list(sample(1000), sample(2000)))
all.equal(f_m0h3n(l), f_jakub(l))
# [1] TRUE
microbenchmark(f_m0h3n(l), f_jakub(l))
# Unit: microseconds
# expr min lq mean median uq max neval
# f_m0h3n(l) 588.973 615.0645 896.9371 651.2065 692.268 2827.242 100
# f_jakub(l) 1022.683 1053.9070 1914.0769 1253.0115 2848.842 3287.898 100
It is evident that f_m0h3n
works better than f_jakub
. The difference is even more significant for larger scales (the time is reduced almost by half).
Upvotes: 2
Reputation: 5104
Could it be a simple rapply
? See this example, where 46 is replaced by 92 (and the other way round, as added by @akrun):
li = list(list(c(1, 46, 107, 69, 1),
c(1, 146, 145, 71, 92, 1)))
# [[1]]
# [[1]][[1]]
# [1] 1 46 107 69 1
#
# [[1]][[2]]
# [1] 1 146 145 71 92 1
rapply(li, function(x) ifelse(x == 46, 92,ifelse(x==92, 46, x)), how = "list")
# [[1]]
# [[1]][[1]]
# [1] 1 92 107 69 1
#
# [[1]][[2]]
# [1] 1 146 145 71 46 1
The how = "list"
makes sure you get the original structure back.
Upvotes: 2