Felipe Alvarenga
Felipe Alvarenga

Reputation: 2652

Given an element of a list, how do I recover its index inside the list?

My problem is basically this:

I have a list, L, where each element is a matrix of the same dimension. I need to multiply each matrix inside this list by its corresponding element in an outside vector h, and then sum all the matrices.

set.seed(101)
L <- replicate(3, matrix(rnorm(4), 2), simplify = FALSE)
h <- 2:4

# I need this
L[[1]] * h[1] + L[[2]] * h[2] + L[[3]] * h[3]

Given that I need to experiment with a different number of matrices, and I have a bunch of them, I've got to do it in a smart way. My idea was

L1 <- lapply(L, function(x) x * h[x])
L2 <- Reduce('+', L1)

Where "h[x]" would be indexing the vector h by the index of the matrix x inside the list L, so I would get

 L1 = list(L[[1]] * h[1], L[[2]] * h[2], L[[3]] * h[3])

So, the question is, how to I get the index of an element in a list by using the element itself? Something like h[L[[m1]]] to get h[1].

Or, if you got any other way of solving my problem, how do I do it?

Upvotes: 5

Views: 232

Answers (3)

lmo
lmo

Reputation: 38500

Using the foreach package, we can get the result as follows:

library(foreach)
foreach(i=seq_along(h), .combine="+") %do% {
  L[[i]] * h[i]
}

The %do% loop runs through performing the element-wise multiplication, then the output summed using the .combine argument. This outputs the same result as Ben's Map-Reduce method.

Upvotes: 2

Frank
Frank

Reputation: 66819

I might do

Reduce(
  function(z,i) z + L[[i]]*h[i], 
  seq_along(L), 
  init = array(0, dim(L[[1]]))
)

Testing it on Ben's example data, I see the same result so I guess it works.

This is similar to an answer @eddi posted on my question about linear combos.

Upvotes: 4

Ben Bolker
Ben Bolker

Reputation: 226182

I think you're looking for mapply()/Map() (Map is slightly easier here because it doesn't try to simplify the results):

?Map:

‘Map’ applies a function to the corresponding elements of given vectors ... ‘Map’ is a simple wrapper to ‘mapply’ which does not attempt to simplify the result ...

?mapply:

‘mapply’ applies ‘FUN’ to the first elements of each ... argument, the second elements, the third elements, and so on

Set up example:

set.seed(101)
L <- replicate(3,matrix(rnorm(4),2),simplify=FALSE)
h <- 2:4

Do it:

Reduce("+",Map("*",L,h))

Upvotes: 6

Related Questions