2011-10-24 14 views
12

私は単純なRcppコードの例を書こうとしています。これは、Rcppパッケージとinlineパッケージでは非常に簡単です。Rcpp :: CharacterVector要素の等価性をテストするには?

しかし、私はどのように平等のための2つの文字要素があるかどうかをテストするのが面倒です。次の例では、2つの文字ベクトルの最初の要素を比較します。しかし、私はそれをコンパイルすることはできません。

トリックとは何ですか?

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 
+0

実装はstring_proxyクラスで次のようになります'定義されている? – James

+0

cxxfunctionで設定する前に、なぜNULLに設定するのですか? – Spacedman

+0

@James Apologies - 'cx [0] == cy [0]' - 編集したはずです。 – Andrie

答えて

11

@kohskeさんの非常に素晴らしい(技術的な)回答ですが、ここではもっとC++です - 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.c_str()xから行くことができますし、どちらかの指標その最初の要素、または単に最初の文字へのポインタを間接参照。より多くのR-っぽい答えは多分、文字列の実際のベクトル上で掃引でき

...

+0

これはありがとうございます - 文字列を比較すること、つまりCharacterVectorの個々の要素を比較することに問題があることに気付きました。このビットを解決すると、次のように定義されたベクトル演算'Rcpp :: Sugar'。 – Andrie

+0

* Rcpp sugar *(ここにはSugarクラスがないのでここにはありません)が好きになる前に、私はループで古い学校を試してみます。 –

+0

ありがとうございますs。 – Andrie

13

はこのお試しください:

// 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. CharacterVectorchar[]ではありません。
  2. operator []は、StringProxyを返します。
  3. StringProxyは、タイプがcharではありません。
  4. StringProxyには、StringProxychar*に変換するメンバー演算子関数char*があります。

したがって、おそらく(char*)cx[0]がポインタです。 C++構文について多くのことを忘れてしまいました...

コンパイラが失敗する理由は、オペレータオーバーロードでタイプ推論が失敗したためです。==StringProxyです。

+0

+1ありがとう、これは動作します。説明に感謝します。 (私は 'char 'にさまざまな形の強制を試みましたが、難しい答えは' char *'を使って強制することでした。 '' Rcpp'という砂糖が '' (cx [0]) ' - 願わくば、誰かがコメントし、正しい' Rcpp'の砂糖構文を与えることができるでしょう – Andrie

+0

@Andrie最初のバージョンが間違っています現在のバージョンは正しい – kohske

12

等価演算子はRcpp 0.10.4で導入されました。

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 
+0

これはいいですね。それは不必要なコピーをたくさん保存します。 – Sameer

関連する問題