如何在声明后将NumericVector初始化为特定大小?

时间:2015-05-08 17:55:31

标签: c++ r rcpp

我编写了以下Rcpp代码,它编译但没有给出预期的结果。

$scope.$watch(function () {
        return $element[0].style.width;
       }, function(newVal, oldVal) {
        console.log('Width changed');
});

x1,返回向量在if语句之外声明,其中返回的向量x1的大小可以变化。但是如果我声明NumericVector的大小,它会创建一个新对象,但是在空向量中返回的x1。

以下代码有效:

    // [[Rcpp::export]]
RObject test_1 (Rcpp::NumericVector& x)
{
  NumericVector x1;
  if (x.size() < 5)
  {
    NumericVector x1(x.size()*3);
    for (int ii = 0; ii < x.size(); ii++)
    {
      x1[ii] = sqrt(x[ii]);
    }
  }
  else
  {
    NumericVector x1(x.size()*2);
    for (int ii = 0; ii < x.size(); ii++)
    {
      x1[ii] = sqrt(x[ii]);
    }
  }
  return x1;
}

这里我声明了temp numericvector,然后将x1设置为该向量。

我刚才这样做了,并且知道有一种方法可以在声明后将NumericVector设置为特定大小,我只是记不清楚。

编辑:编辑代码和问题,以显示在if语句之前如何知道返回向量大小。

3 个答案:

答案 0 :(得分:4)

你可以使用这种风格:

NumericVector x;
if (foo)
    x = NumericVector(1);
else
    x = NumericVector(2);

或者甚至(如果你想避免对生成的矢量进行零初始化)

x = static_cast<NumericVector>(no_init(size));

请注意,当你写

NumericVector x;
if (foo)
    NumericVector x(1);

您实际上正在创建名为NumericVector两个 x个对象 - 一个生活在顶级范围内,另一个生活在{{1}范围内声明。

也就是说,当你写

时,值得理解
if

你实际上正在创建一个对象,而不仅仅是声明一个对象(仅对于内置类型是真的,例如NumericVector x; )。因此,当您编写int时,NumericVector x实际上是使用零参数x构造函数(创建长度为0的数字向量)构造的。

答案 1 :(得分:2)

您可以有条件地resize std::vector<double>Rcpp::wrap(),如下所示:

#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::RObject test_1(const Rcpp::NumericVector& x) {

  std::vector<double> x1;
  if (x.size() < 5) {
    x1.resize(3*x.size());
  } else {
    x1.resize(2*x.size());
  }
  for (int ii = 0; ii < x.size(); ii++) {
    x1[ii] = sqrt(x[ii]);
  }
  return Rcpp::wrap(x1);
}

/*** R

xa <- 1:3
xb <- 1:10

test_1(xa)
# [1] 1.000000 1.414214 1.732051 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

test_1(xb)
#[1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427 3.000000 3.162278 0.000000 0.000000
[13] 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

length(test_1(xa))/length(xa)
#[1] 3
length(test_1(xb))/length(xb) 
#[1] 2

*/

答案 2 :(得分:1)

你可以做这样的事情

RObject test_1 (Rcpp::NumericVector x)
{
    for (int ii = 0; ii < x.size(); ii++)
    {
       x[ii] = sqrt(x[ii]);
    }
    return x;
}

通过传递值,您可以创建与原始版本相同大小的新NumericVector

如果您不想更改API,第二个代码就可以,但不需要临时变量

 RObject test_1 (const Rcpp::NumericVector& x)
{
    NumericVector x1(x.size());
    for (int ii = 0; ii < x.size(); ii++)
    {
       x1[ii] = sqrt(x[ii]);
    }
    return x1;
}