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;
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
CharacterVector sortRcpp2(CharacterVector x) {
return x.sort();
}
- . - ( PROTECT! ) .
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 - .