Index element from list in Rcpp

自作多情 提交于 2019-11-28 23:55:19
Dirk Eddelbuettel

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>

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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!