Index element from list in Rcpp

You have to be explicit at some point. The List class has no idea about the types of elements it contains, it does not know it is a list of matrices.

Dirk has shown you what we usually do, fetch the element as a NumericMatrix and process the matrix.

Here is an alternative that assumes that all elements of your list have the same structure, using a new class template: ListOf with enough glue to make the user code seamless. This just moves to a different place the explicitness.

#include <Rcpp.h>
using namespace Rcpp ;

template <typename WHAT>
class ListOf : public List {
public:
    template <typename T>
    ListOf( const T& x) : List(x){}

    WHAT operator[](int i){ return as<WHAT>( ( (List*)this)->operator[]( i) ) ; }

} ;

// [[Rcpp::export]]
double sacha( ListOf<NumericMatrix> x){
    double sum = 0.0 ; 
    for( int i=0; i<x.size(); i++){
        sum += x[i](0,0) ;    
    }
    return sum ;
}

/*** R
    L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2))
    sacha( L )
*/

When I sourceCpp this file, I get:

> L <- list(matrix(rnorm(9), 3), matrix(1:9, 3), matrix(sqrt(1:4), 2))    
> sacha(L)
[1] 1.087057

Quick ones:

  1. Compound expression in C++ can bite at times; the template magic gets in the way. So just assign from the List object to a whatever the element is, eg a NumericMatrix.

  2. Then pick from the NumericMatrix as you see fit. We have row, col, element, ... access.

  3. Printing can be easier using Rcpp::Rcout << anElement but note that we currently cannot print entire matrices or vectors -- but the int or double types are fine.

Edit:

Here is a sample implementation.

#include <Rcpp.h>

// [[Rcpp::export]]
double sacha(Rcpp::List L) {
    double sum = 0;
    for (int i=0; i<L.size(); i++) {
        Rcpp::NumericMatrix M = L[i];
        double topleft = M(0,0);
        sum += topleft;
        Rcpp::Rcout << "Element is " << topleft << std::endl;
    }
    return sum;    
}

/*** R
set.seed(42)
L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2))
sacha(L) # fix typo   
*/

And its result:

R> Rcpp::sourceCpp('/tmp/sacha.cpp')

R> set.seed(42)

R> L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2))

R> sacha(L)
Element is 1.37096
Element is 1
Element is 1
[1] 3.37096
R>

Tags:

R

Rcpp