16

我正在尝试编写一些简单的 Rcpp 代码示例。Rcpp使用andinline包,这非常容易。

但是我对如何测试两个字符元素是否相等感到困惑。下面的示例比较两个字符向量的第一个元素。但我无法编译它。

诀窍是什么?

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
4

3 回答 3

17

相等运算符已在Rcpp0.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
于 2013-06-19T13:06:51.107 回答
16

试试这个:

  // 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.

不容易解释,但是

  1. CharacterVector不是char[]
  2. operator []返回StringProxy
  3. StringProxy不是char.
  4. StringProxy有一个成员运算符函数char*可以转换StringProxychar*.

所以,也许(char*)cx[0]是一个指针。现在我忘记了很多关于 C++ 语法的事情......

编译失败的原因是运算符重载中的类型推断==失败StringProxy

于 2011-10-24T12:15:26.437 回答
14

@kohske 的非常好的(技术)答案,但这里有更多的 C++ 风格:只需比较字符串!

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")

如果您真的只想比较字符串的第一个字符,那么您可以从xtox.c_str()开始索引其初始元素,或者只是取消引用指向第一个字符的指针。

一个更 R-ish 的答案可能会扫过字符串的实际向量......

于 2011-10-24T12:53:01.933 回答