drastega
drastega

Reputation: 1773

How to append elements from second list to existent elements from first list in R

I have two lists x and y:

x <- list(id1 = list(a = list(t = 5)), id2 = list(a = list(t = 1), b = list(t = 3)), id3 = list(a = list(t = 1), b = list(t = 2)))

y <- list(b = list(k = 7))

I need to modify x list and add corresponding "b" elements from y list to obtain z list:

z <- list(id1 = list(a = list(t = 5)), id2 = list(a = list(t = 1), b = list(t = 3, k = 7)),
  id3 = list(a = list(t = 1), b = list(t = 2, k = 7)))

I try to use list_modify(x, y) and list_merge(x, !!!y) from purrr package but obtain wrong result. How to do this in R?

Upvotes: 1

Views: 314

Answers (4)

James Shoblock
James Shoblock

Reputation: 86

purrr::list_merge works as expected, but when the lists are named it uses the names to find the positions for merging, and your y isn't named properly with id2/id3 for it to merge.

To use list_merge:
y <- list(id2 = list(b = list(k = 7)), id3 = list(b = list(k = 7)))
z2 <- list_merge(x, !!!y)
identical(z, z2)
[1] TRUE

Upvotes: 0

Artem Sokolov
Artem Sokolov

Reputation: 13691

An alternative solution using map_if: apply list_merge to every element in the original list that has at least one subname in common with y:

map_if(x, ~any(names(.) %in% names(y)), list_merge, !!!y)

Upvotes: 0

Allan Cameron
Allan Cameron

Reputation: 173858

In this case you could do:

result <- lapply(x, function(i) {
  if("b" %in% names(i)) i$b <- append(i$b, y$b); i;
  })

Such that

identical(result, z)
#> [1] TRUE

Upvotes: 2

DaveArmstrong
DaveArmstrong

Reputation: 21947

It's not particularly elegant, but you could use a loop to do this. The loop goes over the elements in x and within that, the elements in y. If there is an element in x with the same name as an element in y, the two are concatenated together in z, otherwise, z is just x. Depending on the scale of the real problem, this may be too slow, and perhaps someone can provide a tidy alternative.

z <- vector(mode="list", length = length(x))  
for(i in 1:length(x)){
  for(j in 1:length(y)){
    z[[i]] <- x[[i]]
    if(names(y)[j] %in% names(x[[i]])){
      z[[i]][[names(y)[j]]] <- c(x[[i]][[names(y)[j]]], y[[j]])
    }else{
      
    }
    names(z) <- names(x)
  }
}

Upvotes: 0

Related Questions