Подтвердить что ты не робот

Как протестировать элементы 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
4b9b3361

Ответ 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