這是絕不是一個強大的解決方案,但希望一個跳點,哪裏operator()
超載處理,因爲行&列索引傳遞的int
和string
不同的組合:
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
class MyMat : public Rcpp::NumericMatrix {
public:
MyMat(const Rcpp::NumericMatrix& data_,
const std::vector<std::string>& rnames_,
const std::vector<std::string>& cnames_)
: data(data_),
rnames(rnames_),
cnames(cnames_) {}
double operator()(const std::string& i, const std::string& j) {
typedef std::vector<std::string>::const_iterator cit;
cit it_i = std::find(rnames.begin(), rnames.end(), i);
cit it_j = std::find(cnames.begin(), cnames.end(), j);
int idx_i, idx_j;
if (it_i != rnames.end()) {
idx_i = it_i - rnames.begin();
} else {
idx_i = rnames.size();
}
if (it_j != cnames.end()) {
idx_j = it_j - cnames.begin();
} else {
idx_j = cnames.size();
}
return data(idx_i, idx_j);
}
double operator()(const std::string& i, const size_t j) {
typedef std::vector<std::string>::const_iterator cit;
cit it_i = std::find(rnames.begin(), rnames.end(), i);
int idx_i, idx_j;
if (it_i != rnames.end()) {
idx_i = it_i - rnames.begin();
} else {
idx_i = rnames.size();
}
if (j <= cnames.size()) {
idx_j = j;
} else {
idx_j = cnames.size();
}
return data(idx_i, idx_j);
}
double operator()(const size_t i, const std::string& j) {
typedef std::vector<std::string>::const_iterator cit;
cit it_j = std::find(cnames.begin(), cnames.end(), j);
int idx_i, idx_j;
if (i <= rnames.size()) {
idx_i = i;
} else {
idx_i = rnames.size();
}
if (it_j != cnames.end()) {
idx_j = it_j - cnames.begin();
} else {
idx_j = cnames.size();
}
return data(idx_i, idx_j);
}
double operator()(const int& i, const int& j) {
return data(i, j);
}
private:
Rcpp::NumericMatrix data;
std::vector<std::string> rnames;
std::vector<std::string> cnames;
};
// [[Rcpp::export]]
void test_MyMat(Rcpp::NumericMatrix m)
{
std::vector<std::string> rnames = { "a", "b", "c" };
std::vector<std::string> cnames = { "A", "B", "C" };
MyMat mmObj(m,rnames,cnames);
Rcpp::Rcout << "(Row 1, Column 1)" <<
std::endl;
Rcpp::Rcout << "(b,B) = " << mmObj("b","B") <<
std::endl << "(b,1) = " << mmObj("b",1) <<
std::endl << "(1,B) = " << mmObj(1,"B") <<
std::endl << "(1,1) = " << mmObj(1,1) <<
std::endl;
}
/*** R
x <- matrix(1:9,nrow=3)
test_MyMat(x)
#(Row 1, Column 1)
#(b,B) = 5
#(b,1) = 5
#(1,B) = 5
#(1,1) = 5
x[2,2]
#[1] 5
*/
謝謝!如果這符合rcpp庫的風格,我們應該將這些重載操作符添加到主存儲庫中。 – highBandWidth 2015-02-10 16:18:17
不客氣,就像我說的那樣,這是一個非常小的起點,並且在它被認爲是健壯的之前需要更多的工作。例如,我不確定在C++中執行邊界檢查的正確/慣用方式是什麼,所以我只是(相當懶惰地)強迫出界字符串索引是一個有效(但不正確)的值(例如'else {另外,你肯定希望添加不僅僅是原子(double)的方法,而且還要添加列/行向量,因爲'Rcpp的各種'Matrix'類允許例如'x(1,Rcpp :: _)'(矩陣x的第二行向量)。 – nrussell 2015-02-10 16:26:18
我當然認爲這將是一個有用的功能 - 它只需要更多的時間和精力,而且肯定需要由我的知識豐富的C++程序員來審查。 – nrussell 2015-02-10 16:29:19