[Rcpp-devel] Help with accessing and manipulating List objects

Dirk Eddelbuettel edd at debian.org
Fri Aug 16 13:47:19 CEST 2013


Tal,

You were close.  The error you got indicated that some of (our) wrapping
around (our) class String was missing somehow.  String is pretty new; Romain
just added it a few month ago under funding by Hadley -- and I am still
pretty unfamiliar with it.

Which is why I always go back to std::string. So I converted your code back,
which then built find but ran into one run-time error: you didn't test for
the attribute before extracting it.  That is corrected too.  So your
list-walker is below, with some extra verbose stdout prints.

Hope this helps, it is a nice example and always was a very good question.

Dirk


// Code first


#include <Rcpp.h>
using namespace Rcpp;


bool is_list(RObject x){
    return TYPEOF(x) == VECSXP ;
}

bool is_string(RObject x){
    return TYPEOF(x) == STRSXP && Rf_length(x) == 1 ;
}

bool is_logical(RObject x){
    return TYPEOF(x) == LGLSXP && Rf_length(x) == 1 ;
}


bool is_leaf(RObject x){
    if( TYPEOF(x) != REALSXP ) return false ;
    if( !is_logical( x.attr("leaf") ) ) return false ;
    bool leaf = x.attr( "leaf" ) ;
    return leaf; // either TRUE or FALSE. But often, if it exists - it is TRUE.
}

std::string get_label(RObject x){
    std::string label = "<empty>";
    if (x.hasAttribute("label")) {
	label = as<std::string>(x.attr( "label" )) ;
    }
    return label; // either TRUE or FALSE. But often, if it exists - it is TRUE.
}


void process( List data, std::vector<std::string>& results){
    Rcout << "List with " << data.size() << " elements\n";
    for( int i=0; i<data.size(); i++){
        if( is_list( data[i] ) ){
            // recurse
            Rcout << "Recursing into list\n";
            process( data[i], results ) ;
        } else if( is_leaf( data[i] ) ){
            Rcout << "Looking at leaf\n";
            // we want to collect them. we can use the NumericVector class
            // wince we know this is a numeric vector.
            std::string x_label = get_label(data[i]);
            results.push_back(x_label);
        } // else do nothing
    }
}

// [[Rcpp::export]]
std::vector<std::string> extract_fun(List x){
    std::vector<std::string> results ;
    process(x, results) ;
    return(results) ;
}

/*** R

x <- list(a = 1, b = 2, c = list(ca = 3, cb = 4, 5), 6)
attr(x[[1]], "leaf") = TRUE
attr(x[[1]], "label") = "leaf 1"
attr(x[[3]][[1]], "leaf") = TRUE

attr(x[[2]], "leaf") = TRUE
attr(x[[2]], "label") = "leaf 2"

str(x)

extract_fun(x)

*/


// Output below:

> extract_fun(x)
List with 4 elements
Looking at leaf
Looking at leaf
Recursing into list
List with 3 elements
Looking at leaf
[1] "leaf 1"  "leaf 2"  "<empty>"



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


More information about the Rcpp-devel mailing list