Melierax
Melierax

Reputation: 71

Append each element of a list to each list of a list of lists in R

I would like to append each element of a list to each list of a list of lists.

l1 <- list(list("a", "b", "c"),
           list("d", "e", "f"))
l2 <- list("g", "h")

Expected result :

> l3
[[1]]
[[1]][[1]]
[1] "a"

[[1]][[2]]
[1] "b"

[[1]][[3]]
[1] "c"

[[1]][[4]]
[1] "g"


[[2]]
[[2]][[1]]
[1] "d"

[[2]][[2]]
[1] "e"

[[2]][[3]]
[1] "f"

[[2]][[4]]
[1] "h"

With lapply, I manage to add the same element to the end of each list. I guess that a combination of lapply and do.call would do the trick but I can get it to work as expected...

l3 <- lapply(l1, function(x) do.call(append, list(x,l2)))
# this append both "g" and "h" to each list : 
l3
[[1]]
[[1]][[1]]
[1] "a"

[[1]][[2]]
[1] "b"

[[1]][[3]]
[1] "c"

[[1]][[4]]
[1] "g"

[[1]][[5]]
[1] "h"


[[2]]
[[2]][[1]]
[1] "d"

[[2]][[2]]
[1] "e"

[[2]][[3]]
[1] "f"

[[2]][[4]]
[1] "g"

[[2]][[5]]
[1] "h"

Any idea ? Thanks

Upvotes: 5

Views: 138

Answers (4)

ThomasIsCoding
ThomasIsCoding

Reputation: 102529

The easiest way is as provided by @tmfmnk's Map(...) solution.


Since you have a tag for this question, here is its implementation

> do.call(Map, list(c, l1, l2))
[[1]]
[[1]][[1]]
[1] "a"

[[1]][[2]]
[1] "b"

[[1]][[3]]
[1] "c"

[[1]][[4]]
[1] "g"


[[2]]
[[2]][[1]]
[1] "d"

[[2]][[2]]
[1] "e"

[[2]][[3]]
[1] "f"

[[2]][[4]]
[1] "h" 

Upvotes: 2

random_walk
random_walk

Reputation: 93

The reason your solution does not work is that your function is appending the entire l2 list to each sublist of l1 (as you can observe from the output). If we can assume that l1 and l2 are of the same length, then the lapply solution would be to pass the indices and then append:

Input

l3 <- lapply(1:length(l1), \(x) c(l1[[x]], l2[[x]]))

Output

List of 2
 $ :List of 4
  ..$ : chr "a"
  ..$ : chr "b"
  ..$ : chr "c"
  ..$ : chr "g"
 $ :List of 4
  ..$ : chr "d"
  ..$ : chr "e"
  ..$ : chr "f"
  ..$ : chr "h"

I think the Map/mapply solution already offered is more idiomatic.

Upvotes: 2

s_baldur
s_baldur

Reputation: 33603

Using an explicit loop:

for (i in seq_along(l1)) {
  li[[i]] <- c(l1[[i]], l2[[i]])
}

Upvotes: 4

tmfmnk
tmfmnk

Reputation: 40171

You could use Map() here:

Map(append, l1, l2)

[[1]]
[[1]][[1]]
[1] "a"

[[1]][[2]]
[1] "b"

[[1]][[3]]
[1] "c"

[[1]][[4]]
[1] "g"


[[2]]
[[2]][[1]]
[1] "d"

[[2]][[2]]
[1] "e"

[[2]][[3]]
[1] "f"

[[2]][[4]]
[1] "h"

Upvotes: 9

Related Questions