library(tidyverse)
set.seed(20250104)
A <- data.frame(id = 1:3, x = rnorm(3))
B <- data.frame(id = c(2, 3), y = rnorm(2))
C <- data.frame(id = c(1, 3), z = rnorm(2))
A
B
C
Alexander Krannich’s example:
list(A, B, C) |>
reduce(full_join, by = "id")
Using only {base} (mild edit of David Souza’s reply):
list(A, B, C) |>
Reduce(\(x, y) merge(x, y, by = "id", all = TRUE), x = _)
Getting silly – this all reminded me of Haskell’s foldr1,
implemented (without the Currying) as:
foldr1 <- \(f, xs) {
if (length(xs) == 1)
xs[[1]]
else
f(xs[[1]], foldr1(f, tail(xs, length(xs) - 1)))
}
foldr1(\(x, y) merge(x, y, by = "id", all = TRUE), list(A, B, C))
Here is an easier example:
foldr1(`+`, 1:10)
[1] 55
Which is the same as:
sum(1:10)
[1] 55
LS0tDQp0aXRsZTogIlBsYXlpbmcgYXJvdW5kIHdpdGggcmVkdWNlLCBSZWR1Y2UsIGFuZCBmb2xkcjEiDQphdXRob3I6IEFuZGkgRnVnYXJkDQpkYXRlOiA1IEphbiAyMDI1DQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICBjb2RlX2ZvbGRpbmc6IG5vbmUNCi0tLQ0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KDQpgYGB7cn0NCnNldC5zZWVkKDIwMjUwMTA0KQ0KQSA8LSBkYXRhLmZyYW1lKGlkID0gMTozLCB4ID0gcm5vcm0oMykpDQpCIDwtIGRhdGEuZnJhbWUoaWQgPSBjKDIsIDMpLCB5ID0gcm5vcm0oMikpDQpDIDwtIGRhdGEuZnJhbWUoaWQgPSBjKDEsIDMpLCB6ID0gcm5vcm0oMikpDQpgYGANCg0KYGBge3J9DQpBDQpCDQpDDQpgYGANCg0KQWxleGFuZGVyIEtyYW5uaWNoJ3MgW2V4YW1wbGVdKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wb3N0cy9hbGV4YW5kZXIta3Jhbm5pY2hfcnN0YXRzLXN0YXRpc3RpY3MtcnN0dWRpby1hY3Rpdml0eS03MjgxNjcwODA1ODc5NDU5ODQwLXpWWk8pOg0KDQpgYGB7cn0NCmxpc3QoQSwgQiwgQykgfD4NCiAgcmVkdWNlKGZ1bGxfam9pbiwgYnkgPSAiaWQiKQ0KYGBgDQoNClVzaW5nIG9ubHkge2Jhc2V9IChtaWxkIGVkaXQgb2YgRGF2aWQgU291emEncyBbcmVwbHldKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9mZWVkL3VwZGF0ZS91cm46bGk6YWN0aXZpdHk6NzI4MTY3MDgwNTg3OTQ1OTg0MD9jb21tZW50VXJuPXVybiUzQWxpJTNBY29tbWVudCUzQSUyOGFjdGl2aXR5JTNBNzI4MTY3MDgwNTg3OTQ1OTg0MCUyQzcyODE4MTQ2NTkwNzI5NzA3NTMlMjkmZGFzaENvbW1lbnRVcm49dXJuJTNBbGklM0Fmc2RfY29tbWVudCUzQSUyODcyODE4MTQ2NTkwNzI5NzA3NTMlMkN1cm4lM0FsaSUzQWFjdGl2aXR5JTNBNzI4MTY3MDgwNTg3OTQ1OTg0MCUyOSkpOg0KDQpgYGB7cn0NCmxpc3QoQSwgQiwgQykgfD4NCiAgUmVkdWNlKFwoeCwgeSkgbWVyZ2UoeCwgeSwgYnkgPSAiaWQiLCBhbGwgPSBUUlVFKSwgeCA9IF8pDQpgYGANCg0KR2V0dGluZyBzaWxseSAtLSB0aGlzIGFsbCByZW1pbmRlZCBtZSBvZiBIYXNrZWxsJ3MgW2ZvbGRyMV0oaHR0cHM6Ly9oYWNrYWdlLmhhc2tlbGwub3JnL3BhY2thZ2UvYmFzZS00LjIxLjAuMC9kb2NzL1ByZWx1ZGUuaHRtbCN2OmZvbGRyMSksIGltcGxlbWVudGVkICh3aXRob3V0IHRoZSBDdXJyeWluZykgYXM6DQoNCmBgYHtyfQ0KZm9sZHIxIDwtIFwoZiwgeHMpIHsNCiAgaWYgKGxlbmd0aCh4cykgPT0gMSkNCiAgICB4c1tbMV1dDQogIGVsc2UNCiAgICBmKHhzW1sxXV0sIGZvbGRyMShmLCB0YWlsKHhzLCBsZW5ndGgoeHMpIC0gMSkpKQ0KfQ0KDQpmb2xkcjEoXCh4LCB5KSBtZXJnZSh4LCB5LCBieSA9ICJpZCIsIGFsbCA9IFRSVUUpLCBsaXN0KEEsIEIsIEMpKQ0KYGBgDQoNCkhlcmUgaXMgYW4gZWFzaWVyIGV4YW1wbGU6DQoNCmBgYHtyfQ0KZm9sZHIxKGArYCwgMToxMCkNCmBgYA0KDQpXaGljaCBpcyB0aGUgc2FtZSBhczoNCg0KYGBge3J9DQpzdW0oMToxMCkNCmBgYA0KDQoNCg==