19

Say I have two lists:

list.a <- as.list(c("a", "b", "c"))

list.b <- as.list(c("d", "e", "f"))

I would like to combine these lists recursively, such that the result would be a list of combined elements as a vector like the following:

[[1]]
[1] a d

[[2]]
[1] a e

[[3]]
[1] a f

[[4]]
[1] b d

and so on. I feel like I'm missing something relatively simple here. Any help?

Cheers.

sinclairjesse
  • 1,585
  • 4
  • 17
  • 29
  • 4
    `expand.grid(list.a, list.b)` will give you what you want in a `data.frame` structure, which is arguably more useful. – Matthew Plourde Oct 22 '12 at 19:24
  • I need the resultant list for do.call to generate a series of plots with the x to be the elements of list.a, and the y to be the elements of list.b (i.e., a[1], b[1]; a[1], b[2]; ...; a[n], b[k]). – sinclairjesse Oct 22 '12 at 19:36
  • see also related: http://stackoverflow.com/questions/6515134/combination-of-expand-grid-and-mapply – Ben Bolker Oct 22 '12 at 21:18

6 Answers6

19

expand.grid(list.a, list.b) gives you the desired result in a data.frame. This tends to be the most useful format for working with data in R. However, you could get the exact structure you ask for (save the ordering) with a call to apply and lapply:

result.df <- expand.grid(list.a, list.b)
result.list <- lapply(apply(result.df, 1, identity), unlist)

If you want this list ordered by the first element:

result.list <- result.list[order(sapply(result.list, head, 1))]
sheß
  • 484
  • 4
  • 20
Matthew Plourde
  • 43,932
  • 7
  • 96
  • 113
11

You want mapply (if by "recursively" you mean "in parallel"):

mapply(c, list.a, list.b, SIMPLIFY=FALSE)

Or maybe this is more what you want:

unlist(lapply(list.a, function(a) lapply(list.b, function (b) c(a, b))), recursive=FALSE)
dholstius
  • 1,007
  • 1
  • 7
  • 16
7

Surprised nobody has mentioned this simple one liner:

as.list(outer(list.a,list.b, paste))

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

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

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

[[4]]
[1] "a e"
  • This seems to coerce the input into strings. I tried this with integers, `x <- c(1, 2, 3)` and `y <- c(4, 5, 6)`, and it changes everything into strings. – Steven C. Howell Jul 19 '18 at 13:09
4

This gets you what you are looking for:

unlist(lapply(list.a, function(X) {
    lapply(list.b, function(Y) {
        c(X, Y)
    })
}), recursive=FALSE)
Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
3

Here is a function you can pass lists to to expand

expand.list <- function(...){
   lapply(as.data.frame(t((expand.grid(...)))),c, recursive = TRUE, use.names = FALSE)}

 expand.list(list.a, list.b)
mnel
  • 113,303
  • 27
  • 265
  • 254
1

Here is a somewhat brute force approach that will, given they are the same dimensions, append list.b to list.a recursively using the append function.

# CREATE LIST OBJECTS 
  list.a <- as.list(c("a", "b", "c"))
  list.b <- as.list(c("d", "e", "f"))

# CREATE AN EMPTY LIST TO POPULATE      
list.ab <- list()

# DOUBLE LOOP TO CREATE RECURSIVE COMBINATIONS USING append
    ct=0    
      for( i in 1:length(list.a) ) {    
        for (j in 1:length(list.b) ) {
          ct=ct+1
           list.ab[[ct]] <- append(list.a[[i]], list.b[[j]])     
         } 
       }

# PRINT RESULTS
list.ab
Jeffrey Evans
  • 2,325
  • 12
  • 18