0

How do I concatenate two lists in R in such a way that duplicate elements from the second one will override corresponding elements from the first one?

I tried c(), but it keeps duplicates:

l1 <- list(a = 1, b = 2)
l1 <- c(l1, list(b = 3, c = 4))

# $a
# [1] 1
# 
# $b
# [1] 2
# 
# $b
# [1] 3
#
# $c
# [1] 4

I want something that will produce this instead:

# $a
# [1] 1
# 
# $b
# [1] 3
#
# $c
# [1] 4

Hope that there exists something simpler than calling some *apply function?

Tomas
  • 57,621
  • 49
  • 238
  • 373

4 Answers4

5

This works with duplicated:

> l1[!duplicated(names(l1), fromLast=TRUE)]
$a
[1] 1

$b
[1] 3

$c
[1] 4
Peter Diakumis
  • 3,942
  • 2
  • 28
  • 26
  • thanks this works, but I would still hope for something simpler for such a basic thing... – Tomas Mar 05 '15 at 10:27
  • 2
    @TMS what could be possibly simpler than just use `duplicated` combined with simple subsetting? Did you ever see anything simpler in another language? This code will be also very efficient. – David Arenburg Mar 05 '15 at 10:47
  • perhaps something like `l1 + l2`? :-) I mean, this feels so basic that there should be an operator for that. – Tomas Mar 05 '15 at 13:04
  • 2
    @TMS, why would this be a `+` condition? If you're not happy with the other straightforward and standard ways of achieving what you want, you might just have to write the solution yourself. If you are [unhappy with how something is designed](http://stackoverflow.com/q/27943961/1270695) and others offer you solutions that are efficient and work *but you are still unhappy because it doesn't work using your expected syntax*, then you're the best one to try to make your expected syntax work by writing your own function or method or operator or something else. :-/ – A5C1D2H2I1M1N2O1R2T1 Mar 05 '15 at 16:23
4

I suspect that you could get the behavior you want by using the "rlist" package; specifically, list.merge seems to do what you are looking for:

l1 <- list(a = 1, b = 2)
l2 <- list(b = 3, c = 4)
library(rlist)
list.merge(l1, l2)
# $a
# [1] 1
# 
# $b
# [1] 3
# 
# $c
# [1] 4 

Try list.merge(l2, l1) to get a sense of the function's behavior.


If you have just two lists, as noted by @PeterDee, the list.merge function pretty much makes modifyList accept more than two lists. Thus, for this particular example, you could skip loading any packages and directly do:

modifyList(l1, l2)
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
1

I am sure there is a quicker way than:

l1 <- list(a = 1, b = 2)
l2 <- list(b = 3, c = 4)

l1 <- c(l1[!(names(l1) %in% names(l2))],  l2)

You take the names of the l1 that are not in l2 and concatenate the two lists

dimitris_ps
  • 5,849
  • 3
  • 29
  • 55
  • thanks this works, but I would still hope for something simpler for such a basic thing... – Tomas Mar 05 '15 at 10:27
0

I would suggest union:

l1 <- list(a = 1, b = 3)
l2 <- list(b = 3, c = 4)

union(l1, l2)

This works like a union in mathematics (Wiki link)

martin
  • 63
  • 5