MayaGans
MayaGans

Reputation: 1845

Join 2 nested lists

I want to combine two lists

list_1 <- list(LIST1 = list(list("a"), list("b"), list("c")))
list_2 <- list(LIST2 = list(list("1"), list("2"), list("3")))

Desired Output:

combined_list <- list()
combined_list[[1]] <- c("a", "1")
combined_list[[2]] <- c("b", "2")
combined_list[[3]] <- c("c", "3")

I have a nasty for loop way of doing this but I'd like to clean it up using purrr maybe? Any help appreciated!!

Upvotes: 5

Views: 713

Answers (3)

Artem Sokolov
Artem Sokolov

Reputation: 13731

Here's a variant that recursively concatenates two nested lists of the same structure and preserves that structure

# Add additional checks if you expect the structures of .x and .y may differ
f <- function(.x, .y)
  if(is.list(.x)) purrr::map2(.x, .y, f) else c(.x, .y)

res <- f( list_1, list_2 )
# ...is identical to...
# list(LIST1 = list(list(c("a","1")), list(c("b","2")), list(c("c","3"))))

You can then unroll the structure as needed. For example, to get the desired output, you can do

purrr::flatten(purrr::flatten(res))
# [[1]]
# [1] "a" "1"
# 
# [[2]]
# [1] "b" "2"
# 
# [[3]]
# [1] "c" "3"

Upvotes: 3

Vitali Avagyan
Vitali Avagyan

Reputation: 1203

You can actually use this one line:

map2(list_1,list_2,map2,~paste(c(..1,..2)))[[1]]

Output:

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

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

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

Upvotes: 0

Calum You
Calum You

Reputation: 15072

There's a few odd things with your input and so I am not sure if this will wholly generalize to your real situation. If it does not, then please expand your example. Each list has only one element, for one, and the individual letters are also wrapped in a list of their own. I get around that by indexing the input lists with [[1]] and flattening the output with as.character.

list_1 <- list(LIST1 = list(list("a"), list("b"), list("c")))
list_2 <- list(LIST2 = list(list("1"), list("2"), list("3")))

library(purrr)
combined_list <- map2(list_1[[1]], list_2[[1]], c) %>%
  map(as.character)
str(combined_list)
#> List of 3
#>  $ : chr [1:2] "a" "1"
#>  $ : chr [1:2] "b" "2"
#>  $ : chr [1:2] "c" "3"

Created on 2019-11-07 by the reprex package (v0.3.0)

Upvotes: 2

Related Questions