[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