[Rcpp-devel] Filling a list with iterator, or setting names from CharacterVector/SEXP?

Dirk Eddelbuettel edd at debian.org
Fri Aug 31 13:50:33 CEST 2012


On 30 August 2012 at 21:52, Christian Gunning wrote:
| I'm trying to implement a class lets me access elements by name in the
| actual C++ code.
| I'm handing in a matrix from R, and using the colnames and rownames of
| the matrix to generate a named list containing the relevant indices.
| My main interest here is legible code -- I'm trying to set up
| user-modifiable markov chain model specification functions in C++ that
| are relatively idiot-proof and can be error-checked (so far the idiot
| is just me). Initial tests indicate that the speed cost of list access
| are very small compared to the actual model code.  I'm not sure if I'm
| really abusing lists here, and any suggestions on other directions to
| explore would be appreciated.

Nice. Yet another MCMC helper via Rcpp, I like it. 
 
| In any case, I finally got this working, but it's really ugly, and I
| feel like there has to be an easier way to do this -- iterators?.

Yes -- I needed this the other day to return what I got in C++ as a
std::vector<std::string> vecstr. I used something like

         Rcpp::CharacterVector charvec( vecstr.begin(), vecstr.end() )

but I later realized that Rcpp::wrap() already covered this case so it
reduced to

	return vecstr;

instead :)   

You should be able to to do better than your loop below as you already have a
vector in 'rownames'. My not just transform that into a list directly as below?

Dirk


R> library(inline)
R> 
R> f <- cxxfunction(signature(xs="character"), plugin="Rcpp", body='
+     Rcpp::CharacterVector xv(xs);
+     return Rcpp::List( xv );
+ ')
R> 
R> x <- c("Moe", "Curly", "Larry")
R> f(x)
[[1]]
[1] "Moe"

[[2]]
[1] "Curly"

[[3]]
[1] "Larry"

R> 

Dirk

| I looked at the doxygen docs for List instantiation and methods, and I
| admit it's still Latin to me (which is a little better than Greek...)
| This is built with a vanilla Rcpp.package.skeleton(modules=TRUE),
| replacing the World class with the following:
| 
| 
| using namespace Rcpp ;
| class World {
|     public:
|         World(SEXP my_) : my(my_) {
|             mynames = my.attr("dimnames");
|             CharacterVector rownames = mynames[0];
|             nrows = rownames.size();
|             myrows = Rcpp::List(0);
|             for (int i=0; i<nrows; i++) {
|                 Rcpp::CharacterVector tmpname(rownames[i]);
|                 std::string thisname = as<std::string>(tmpname);
|                 myrows[thisname] = i;
|             }
|         }
|        Rcpp::List myrows;
|        Rcpp::List getrows() {
|            return myrows;
|       }
| 
|     private:
|         Rcpp::NumericMatrix my;
|         Rcpp::List mynames;
|         int  nrows;
| };
| 
| RCPP_MODULE(yada){
|     using namespace Rcpp ;
|     class_<World>( "World" )
|     // expose the default constructor
|     .constructor<SEXP>()
|     .method( "getrows", &World::getrows     , "test function, return
| something" )
|     ;
| }
| 
| In R:
| require(Rcpp)
| Rcpp.package.skeleton('FillList', module=T)
| 
| In shell:
| replace FillList/src/rcpp_module.cpp  contents from "class World" to
| end with the above
| R CMD INSTALL FillList
| 
| In R:
| inmat = matrix(1:6, nrow=2);
| colnames(inmat) = letters[1:ncol(inmat)];
| rownames(inmat) = letters[1:nrow(inmat)];
| require(FillList)
| aa = new(World, inmat)
| aa$getrows()
| 
| thanks,
| Christian
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

-- 
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com  


More information about the Rcpp-devel mailing list