Given a list of two lists, I am trying to obtain, without using for loops, a list of all element-wise products of the first list with the second. For example:
Have no idea if this is fast or memory intensive just that it works, Joris Meys's answer is more eloquent:
x <- expand.grid(1:length(a), 1:length(b))
x <- x[order(x$Var1), ] #gives the order you asked for
FUN <- function(i) diag(outer(a[[x[i, 1]]], b[[x[i, 2]]], "*"))
sapply(1:nrow(x), FUN) #I like this out put
lapply(1:nrow(x), FUN) #This one matches what you asked for
EDIT: Now that Brian introduced benchmarking (which I love (LINK)) I have to respond. I actually have a faster answer using what I call expand.grid2 that's a lighter weight version of the original that I stole from HERE. I was going to throw it up before but when I saw how fast Joris's is I figured why bother, both short and sweet but also fast. But now that Diggs has dug I figured I'd throw up here the expand.grid2
for educational purposes.
expand.grid2 <-function(seq1,seq2) {
cbind(Var1 = rep.int(seq1, length(seq2)),
Var2 = rep.int(seq2, rep.int(length(seq1),length(seq2))))
}
x <- expand.grid2(1:length(a), 1:length(b))
x <- x[order(x[,'Var1']), ] #gives the order you asked for
FUN <- function(i) diag(outer(a[[x[i, 1]]], b[[x[i, 2]]], "*"))
lapply(1:nrow(x), FUN)
Here's the results (same labeling as Bryan's except TylerEG2 is using the expand.grid2
):
Unit: microseconds
expr min lq median uq max
1 DiggsL(a, b) 5102.296 5307.816 5471.578 5887.516 70965.58
2 DiggsM(a, b) 384.912 428.769 443.466 461.428 36213.89
3 Joris(a, b) 91.446 105.210 123.172 130.171 16833.47
4 TylerEG2(a, b) 392.377 425.503 438.100 453.263 32208.94
5 TylerL(a, b) 1752.398 1808.852 1847.577 1975.880 49214.10
6 TylerM(a, b) 1827.515 1888.867 1925.959 2090.421 75766.01
7 Wojciech(a, b) 1719.740 1771.760 1807.686 1924.325 81666.12
And if I take the ordering step out I can squeak out even more but it still isn't close to Joris's answer.