Convert SEXP from R to a string vector in C ++

I am trying to pass a character vector (i.e. a string vector) from R to C / C ++ for sorting and other purposes. When using Rcpp, this is easy to do with the following code:

#include <Rcpp.h>
#include <vector>
#include <string>
using namespace Rcpp;

// [[Rcpp::export]]
CharacterVector sort(CharacterVector x) {

  std::sort(x.begin(), x.end());
  return x;
}

However, since this is my only planned use of C ++ in this package, it is hardly worth imagining a dependency on Rcpp. To do the same without him is not so simple. Integers are simple enough:

#include <R.h>
#include <Rdefines.h>
#include <algorithm>
#include <string.h>
using namespace std;
SEXP sort(SEXP x) {
  int* xx = INTEGER(x);
  std::sort(xx, xx+LENGTH(x));
  return(x);
}

But no std::vector<string>or char**equivalent INTEGER().

How can I emulate the same code without introducing an Rcpp dependency?

There are questions here that discuss how to use CHAR(STRING_ELT())to convert a single string, but it is not clear how to convert to an array / vector of strings.

+4
1

STRING_PTR() INTEGER(). a SEXP *. SEXP R; STRING_PTR(x)[0] STRING_ELT(x, 0). SEXP , const char * ; CHAR(STRING_PTR(x)[i]). file.path(R.home("include"), "Rinternals.h")

std::sort(STRING_PTR(x), STRING_PTR(x) + LENGTH(x)) , , - STRING_PTR(x)[i] < STRING_PTR(x)[j]. C , strcmp(CHAR(STRING_PTR(x)[i]), CHAR(STRING_PTR(x)[j])). std::sort(x.begin(), x.end()) ( , Rcpp - x.sort()).

, SEXP, const char * ( CHAR()) .

struct CMP_CHAR {
    bool operator()(SEXP x, SEXP y) {
        return strcmp(CHAR(x), CHAR(y)) < 0;
    }
} cmp_char;

// [[Rcpp::export]]
SEXP sortcpp0(SEXP x) {
    std::sort(STRING_PTR(x), STRING_PTR(x) + LENGTH(x), cmp_char);
    return x;
}

( Rcpp , sourceCpp(), , R CMD SHLIB Rcpp).

, , , R , - , x y , x.

> n = 10; set.seed(123); x = y = sample(as.character(1:n))
> sortcpp0(x); y
 [1] "1"  "10" "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9" 
 [1] "1"  "10" "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"

, Rcpp

// [[Rcpp::export]]
CharacterVector sortRcpp2(CharacterVector x) {
    return x.sort();
}

- . - ( PROTECT! ) .

// [[Rcpp::export]]
SEXP sortcpp(SEXP x) {
    x = PROTECT(Rf_duplicate(x));
    std::sort(STRING_PTR(x), STRING_PTR(x) + LENGTH(x), cmp_char);
    UNPROTECT(x);
    return x;
}

> n = 10; set.seed(123); x = y = sample(as.character(1:n))
> sortcpp(x); y
 [1] "1"  "10" "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9" 
 [1] "3"  "8"  "4"  "7"  "6"  "1"  "10" "9"  "2"  "5" 

, Rcpp (Rcpp::clone(), thanks @DirkEddelbuettel), , ++.

@Spacedman , R-, , - ​​ C, ( ) (, NA , ). ( ...)

> library(microbenchmark)
> n = 1e4; set.seed(123); x = sample(as.character(1:n))
> identical(sort(x), sortcpp(x))
[1] TRUE
> microbenchmark(sort(x), sortcpp(x))
Unit: milliseconds
       expr       min        lq      mean    median        uq       max neval
    sort(x) 56.061580 56.563541 57.034674 56.997618 57.667031 59.003068   100
 sortcpp(x)  3.542409  3.556655  3.610071  3.582562  3.662196  3.800319   100

, , StackOverflow [r] STRING_PTR - .

+6

Source: https://habr.com/ru/post/1618355/


All Articles