On 31 August 2012 at 23:44, Christian Gunning wrote:
| On Fri, Aug 31, 2012 at 5:50 AM, Dirk Eddelbuettel <edd at debian.org> wrote:
| >
| > 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() )
|
| Ok, I was wondering about std::vector. But how do I go the other way
| and get a std::vector<std::string> vecstr from a CharacterVector?
| Can I use as<std::string>() and then iterate over the CharacterVector?
Sure, works via Rcpp::as< std::vector< std::string> >(foo)
| My use-case is access-by-name. So in this example I want, for example:
| R> f(x)
| [["Moe"]]
| [1] 1
|
| [["Curly"]]
| [1] 2
|
| Of course, I can just hand in list(Moe=1, Curly=2), but then I still
| don't know how to get the names of the list out of the list into a
| CharacterVector or std::vector<std::string>. Does this sort of make
| sense?
I am not sure what it is that you want but if you look e.g. at RcppExamples
and its examples related to parameter passage in and out, you see that we can
pick _arbitrary_ objects in and out of Rcpp::Lists by name. Does that help?
Dirk
| Can I use as<std::string>() and then iterate over the CharacterVector?
Sure, works via Rcpp::as< std::vector< std::string> >(foo)
Perfect, thanks. Revised example included below for reference.
I am not sure what it is that you want but if you look e.g. at RcppExamples
and its examples related to parameter passage in and out, you see that we can
pick _arbitrary_ objects in and out of Rcpp::Lists by name. Does that help?
It looks like I just answered my own question -- I'd like to get the
actual *names* of the list on the C++ side:
Rcpp::List listnames = mylist.attr("names");
Is the .attr mechanism general to any named attribute that belongs to an SEXP?
The ultimate goal is C++ error-checking of list-access names -- if the
named element is not present in the list, print the offending name and
throw an exception. Is there an easier way to do this than checking
the supplied name (as std::string) against the vector of list names?
I admit this looks convoluted, but it's a minimal example...
using namespace Rcpp ;
class World {
public:
World(SEXP mymat_) : mymat(mymat_), myrows(0), mycols(0) {
Rcpp::List mynames = mymat.attr("dimnames");
CharacterVector rownames_ = mynames[0];
rownames = Rcpp::as< std::vector< std::string>
(rownames_);
nrows = rownames.size();
for (int i=0; i<nrows; i++) {
myrows[rownames[i]] = i;
}
rownames_list = myrows.attr("names");
}
SEXP get(std::string varname) {
if (debug) {
// check that varname is in rownames_list
}
return myrows[varname];
}
void put(std::string varname, int val){
if (debug) {
// check that varname is in rownames_list
}
myrows[varname] = val;
};
public:
Rcpp::List myrows, mycols;
private:
std::vector<std::string> rownames;
Rcpp::List rownames_list ;
Rcpp::NumericMatrix mymat;
Rcpp::List mynames;
int nrows, ncols;
bool debug;
};
RCPP_MODULE(yada){
using namespace Rcpp ;
class_<World>( "World" )
.constructor<SEXP>()
.method( "get", &World::get , "get a list element" )
.method( "put", &World::put , "put a list element" )
;
}
## in R
mytest <- function(nr=2, nc=3) {
inmat = matrix(1:(nr*nc), nrow=nr);
colnames(inmat) = letters[1:nc];
rownames(inmat) = letters[1:nr];
aa <- new(World, inmat)
ret1 <- aa$get("a")
aa$put("a", 17L)
ret2 <- aa$get("a")
list(ret1, ret2)
}
A man, a plan, a cat, a ham, a yak, a yam, a hat, a canal ? Panama!
On 7 September 2012 at 01:32, Christian Gunning wrote:
| > | Can I use as<std::string>() and then iterate over the CharacterVector?
| >
| > Sure, works via Rcpp::as< std::vector< std::string> >(foo)
|
| Perfect, thanks. Revised example included below for reference.
|
| > I am not sure what it is that you want but if you look e.g. at RcppExamples
| > and its examples related to parameter passage in and out, you see that we can
| > pick _arbitrary_ objects in and out of Rcpp::Lists by name. Does that help?
|
| It looks like I just answered my own question -- I'd like to get the
| actual *names* of the list on the C++ side:
| Rcpp::List listnames = mylist.attr("names");
| Is the .attr mechanism general to any named attribute that belongs to an SEXP?
|
| The ultimate goal is C++ error-checking of list-access names -- if the
| named element is not present in the list, print the offending name and
| throw an exception. Is there an easier way to do this than checking
| the supplied name (as std::string) against the vector of list names?
I think the STL has algorithms for it, ie something like the R code
"foo" %in% vec
then works via a single call with one 'token' and a vector. The function may
be called find() -- I can't quite recall but I think I used this before.
Dirk
| I admit this looks convoluted, but it's a minimal example...
|
| using namespace Rcpp ;
| class World {
| public:
| World(SEXP mymat_) : mymat(mymat_), myrows(0), mycols(0) {
| Rcpp::List mynames = mymat.attr("dimnames");
| CharacterVector rownames_ = mynames[0];
| rownames = Rcpp::as< std::vector< std::string>
| >(rownames_);
| nrows = rownames.size();
| for (int i=0; i<nrows; i++) {
| myrows[rownames[i]] = i;
| }
| rownames_list = myrows.attr("names");
| }
| SEXP get(std::string varname) {
| if (debug) {
| // check that varname is in rownames_list
| }
| return myrows[varname];
| }
| void put(std::string varname, int val){
| if (debug) {
| // check that varname is in rownames_list
| }
| myrows[varname] = val;
| };
| public:
| Rcpp::List myrows, mycols;
| private:
| std::vector<std::string> rownames;
| Rcpp::List rownames_list ;
| Rcpp::NumericMatrix mymat;
| Rcpp::List mynames;
| int nrows, ncols;
| bool debug;
| };
|
| RCPP_MODULE(yada){
| using namespace Rcpp ;
| class_<World>( "World" )
| .constructor<SEXP>()
| .method( "get", &World::get , "get a list element" )
| .method( "put", &World::put , "put a list element" )
| ;
| }
|
|
| ## in R
| mytest <- function(nr=2, nc=3) {
| inmat = matrix(1:(nr*nc), nrow=nr);
| colnames(inmat) = letters[1:nc];
| rownames(inmat) = letters[1:nr];
| aa <- new(World, inmat)
| ret1 <- aa$get("a")
| aa$put("a", 17L)
| ret2 <- aa$get("a")
| list(ret1, ret2)
| }
|
|
| --
| A man, a plan, a cat, a ham, a yak, a yam, a hat, a canal ? Panama!