Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
498 views
in Technique[技术] by (71.8m points)

r - Combine/merge lists by elements names

I have two lists, whose elements have partially overlapping names, which I need to merge/combine together into a single list, element by element:

> lst1 <- list(integers=c(1:7), letters=letters[1:5],
                words=c("two", "strings"))
> lst2 <- list(letters=letters[1:10], booleans=c(TRUE, TRUE, FALSE, TRUE),
                words=c("another", "two"), floats=c(1.2, 2.4, 3.8, 5.6))

> lst1
$integers
[1] 1 2 3 4 5 6 7

$letters
[1] "a" "b" "c" "d" "e"

$words
[1] "two"     "strings"

> lst2
$letters
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

$booleans
[1]  TRUE  TRUE FALSE  TRUE

$words
[1] "another" "two"    

$floats
[1] 1.2 2.4 3.8 5.6

I tried using mapply, which basically combines the two lists by index (i.e.: "[["), while I need to combine them by name (i.e.: "$"). In addition, since the lists have different lengths, the recycling rule is applied (with rather unpredictable results).

> mapply(c, lst1, lst2)
$integers
 [1] "1" "2" "3" "4" "5" "6" "7" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

$letters
[1] "a"     "b"     "c"     "d"     "e"     "TRUE"  "TRUE"  "FALSE" "TRUE" 

$words
[1] "two"     "strings" "another" "two"    

$<NA>
 [1] 1.0 2.0 3.0 4.0 5.0 6.0 7.0 1.2 2.4 3.8 5.6

Warning message:
In mapply(c, lst1, lst2) :
  longer argument not a multiple of length of shorter

As you might imagine, what I'm looking for is:

$integers
[1] 1 2 3 4 5 6 7

$letters
[1] "a" "b" "c" "d" "e" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

$words
[1] "two"     "strings"   "another" "two"

$booleans
[1]  TRUE  TRUE FALSE  TRUE

$floats
[1] 1.2 2.4 3.8 5.6

Is there any way to achieve that? Thank you!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do:

keys <- unique(c(names(lst1), names(lst2)))
setNames(mapply(c, lst1[keys], lst2[keys]), keys)

Generalization to any number of lists would require a mix of do.call and lapply:

l <- list(lst1, lst2, lst1)
keys <- unique(unlist(lapply(l, names)))
setNames(do.call(mapply, c(FUN=c, lapply(l, `[`, keys))), keys)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...