我正在尝试将某些字符数据转换为数字,如下所示。数据将带有特殊的字符,所以我必须把它们拿出来。我将数据转换为std:string以搜索特殊字符。它会在内存中创建一个新变量吗?我想知道是否有更好的方法来做到这一点。
NumericVector converter_ra_(Rcpp::RObject x){
if(x.sexp_type() == STRSXP){
CharacterVector y(x);
NumericVector resultado(y.size());
for(unsigned int i = 0; i < y.size(); i++){
std::string ra_string = Rcpp::as<std::string>(y[i]);
//std::cout << ra_string << std::endl;
double t = 0;
int base = 0;
for(int j = (int)ra_string.size(); j >= 0; j--){
if(ra_string[j] >= 48 && ra_string[j] <= 57){
t += ((ra_string[j] - '0') * base_m[base]);
base++;
}
}
//std::cout << t << std::endl;
resultado[i] = t;
}
return resultado;
}else if(x.sexp_type() == REALSXP){
return NumericVector(x);
}
return NumericVector();
}
答案 0 :(得分:4)
它是否在内存中创建了一个新变量?
如果输入对象实际上是一个数字向量(REALSXP
)并且您只是返回,例如as<NumericVector>(input)
,然后不会创建其他变量。在任何其他情况下,当然需要为返回的对象分配新的内存。例如,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector demo(RObject x) {
if (x.sexp_type() == REALSXP) {
return as<NumericVector>(x);
}
return NumericVector::create();
}
/*** R
y <- rnorm(3)
z <- letters[1:3]
data.table::address(y)
# [1] "0x6828398"
data.table::address(demo(y))
# [1] "0x6828398"
data.table::address(z)
# [1] "0x68286f8"
data.table::address(demo(z))
# [1] "0x5c7eea0"
*/
我想知道是否有更好的方法来做到这一点。
首先,您需要定义&#34;更好&#34;:
就个人而言,我会从最后一个定义开始,因为它通常需要一个或多个其他定义。例如,在这种方法中我们
Predicate
而不是尝试在本地实现的函数对象isdigit
Predicate
确定的字符;如果有必要,使用std::atoi
将剩余的内容转换为double
(再次,而不是尝试自己实现)as
转换器 - 将STRSXP
转换为std::vector<std::string>
std::transform
将其转换为结果向量#include <Rcpp.h>
using namespace Rcpp;
struct Predicate {
bool operator()(char c) const
{ return !(c == '.' || std::isdigit(c)); }
};
struct Converter {
double operator()(std::string s) const {
s.erase(
std::remove_if(s.begin(), s.end(), Predicate()),
s.end()
);
return s.empty() ? NA_REAL : std::atof(s.c_str());
}
};
// [[Rcpp::export]]
NumericVector convert(RObject obj) {
if (obj.sexp_type() == REALSXP) {
return as<NumericVector>(obj);
}
if (obj.sexp_type() != STRSXP) {
return NumericVector::create();
}
std::vector<std::string> x = as<std::vector<std::string> >(obj);
NumericVector res(x.size(), NA_REAL);
std::transform(x.begin(), x.end(), res.begin(), Converter());
return res;
}
测试此功能以实现最低限度的功能,
x <- c("123 4", "abc 1567.35 def", "abcdef", "")
convert(x)
# [1] 1234.00 1567.35 NA NA
(y <- rnorm(3))
# [1] 1.04201552 -0.08965042 -0.88236960
convert(y)
# [1] 1.04201552 -0.08965042 -0.88236960
convert(list())
# numeric(0)
这是否与经验丰富的C或C ++程序员手写的一样高效?几乎肯定不是。但是,由于我们使用了库函数和常用习语,因此它相当简洁,可能没有错误,而且即使在快速浏览的情况下,其意图也相当明显。如果您需要更快的东西,那么可能会进行一些优化,但如果没有首先进行基准测试和分析,就不需要在该前提下开始。