Как протестировать элементы Rcpp:: CharacterVector для равенства?
Я пытаюсь написать несколько простых примеров кода Rcpp. Это замечательно легко с пакетами Rcpp
и inline
.
Но я в тупике о том, как проверить, являются ли два символьных элемента для равенства. В следующем примере сравниваются первые элементы двух символьных векторов. Но я не могу его скомпилировать.
Каков трюк?
library(Rcpp)
library(inline)
cCode <- '
Rcpp::CharacterVector cx(x);
Rcpp::CharacterVector cy(y);
Rcpp::LogicalVector r(1);
r[0] = (cx[0] == cy[0]);
return(r);
'
cCharCompare <- cxxfunction(signature(x="character", y="character"),
plugin="Rcpp", body=cCode)
cCharCompare("a", "b")
-
Сравнение с использованием ==
отлично работает, если один из двух элементов является константой. Следующий код компилирует и дает ожидаемые результаты:
cCode <- '
Rcpp::CharacterVector cx(x);
Rcpp::LogicalVector r(1);
r[0] = (cx[0] == "a");
return(r);
'
cCharCompareA <- cxxfunction(signature(x="character"), plugin="Rcpp", body=cCode)
cCharCompareA("a")
[1] TRUE
cCharCompareA("b")
[1] FALSE
Ответы
Ответ 1
Очень приятный (технический) ответ от @kohske, но вот что-то еще С++ - ish: просто сравните строки!
library(inline) ## implies library(Rcpp) when we use the plugin
cCode <- '
std::string cx = Rcpp::as<std::string>(x);
std::string cy = Rcpp::as<std::string>(y);
bool res = (cx == cy);
return(Rcpp::wrap(res));
'
cCharCompare <- cxxfunction(signature(x="character", y="character"),
plugin="Rcpp", body=cCode)
cCharCompare("a", "b")
Если вы действительно хотите сравнить только первый символ строк, вы можете перейти от x
в x.c_str()
и либо проиндексировать его начальный элемент, либо просто разыменовать указатель на первый char.
Более R-ish-ответ может быть развернут по фактическим векторам строк...
Ответ 2
Попробуйте следующее:
// r[0] = (cx[0] == cy[0]);
// r[0] = ((char*)cx[0] == (char*)cy[0]); <- this is wrong
r[0] = (*(char*)cx[0] == *(char*)cy[0]); // this is correct.
Нелегко объяснить, но
-
CharacterVector
не char[]
.
-
operator []
возвращает StringProxy
.
-
StringProxy
не является типом char
.
-
StringProxy
имеет функцию-член-член char*
, которая преобразует StringProxy
в char*
.
Итак, возможно, (char*)cx[0]
является указателем.
Теперь я забыл многое о синтаксисе С++...
Поводом к отказу компиляции является отказ вывода типа при перегрузке оператора ==
для StringProxy
.
Ответ 3
В равенстве Rcpp
0.10.4 введен оператор равенства. Реализация выглядит так в классе string_proxy
:
bool operator==( const string_proxy& other){
return strcmp( begin(), other.begin() ) == 0 ;
}
Итак, теперь мы можем написать:
#include <Rcpp.h>
using namespace Rcpp ;
// [[Rcpp::export]]
LogicalVector test( CharacterVector x, CharacterVector y){
Rcpp::LogicalVector r(x.size());
for( int i=0; i<x.size(); i++){
r[i] = (x[i] == y[i]);
}
return(r);
}
И что-то подобное используется в наших модульных тестах:
> test(letters, letters)
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[16] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE