Reputation: 1062
I have the following lists:
l1 <- list(a = 3, b = 4, c = 8, d = 1)
l2 <- list(a = 3, b = 2, c = 5, d = 1, f = 4, g = 13)
How can merge both lists by summing the items in both lists based on their names, as:
l1 + l2 = list(a=6, b=6, c=13, d=2, f=4, g=13)
Upvotes: 4
Views: 654
Reputation: 388817
A slightly different approach,
l1 <- list(a = 3, b = 4, c = 8, d = 1)
l2 <- list(a = 3, b = 2, c = 5, d = 1, f = 4, g = 13)
a <- l1[intersect(names(l1), names(l2))]
b <- l2[intersect(names(l1), names(l2))]
ab <- as.numeric(a) + as.numeric(b)
c <- as.numeric(l1[!(l1 %in% a)])
d <- as.numeric(l2[!(l2 %in% b)])
c(ab, c, d)
# [1] 6 6 13 2 4 13
Upvotes: 0
Reputation: 886948
One option would be to melt
both the list
s to data.frame, merge
them, do the rowSums
on the numeric columns and convert back to list
.
library(reshape2)
d1 <- merge(melt(l1), melt(l2), by='L1', all=TRUE)
setNames(as.list(rowSums(d1[-1], na.rm=TRUE)), d1$L1)
#$a
#[1] 6
#$b
#[1] 6
#$c
#[1] 13
#$d
#[1] 2
#$f
#[1] 4
#$g
#[1] 13
Or we create the unique names
of both 'l1' and 'l2' ('nm1'). Loop over 'nm1', replace
the NULL elements with 0 and do the +
.
nm1 <- union(names(l1), names(l2))
lapply(nm1, function(x) {v1 <- l1[[x]]
v2 <- l2[[x]]
replace(v1, is.null(v1), 0) +
replace(v2, is.null(v2), 0)
})
Upvotes: 3
Reputation: 17359
You could approach it with dplyr
as follows:
l1 <- list(a = 3, b = 4, c = 8, d = 1)
l2 <- list(a = 3, b = 2, c = 5, d = 1, f = 4, g = 13)
library(dplyr)
bind_rows(lapply(list(l1, l2), as.data.frame)) %>%
colSums(na.rm=TRUE) %>%
as.list()
Upvotes: 4