对于这样的任务,最好跳过有问题的索引。在标准C++
中,我们会检查索引并跳过它。像这样的东西:
// [[Rcpp::export]]
arma::vec rcpp_sum (arma::vec y, int n){
arma::vec x(n);
for (int i = 0; i < n; i++) {
x[i] = 0; // Initialize value
for (int j = 0; j < y.size(); ++j) {
if (i != j) {
x[i] += y[j];
}
}
}
return x;
}
在上面,我们正在远离糖语法。IMO 在这种情况下没关系,因为替代方案并不过分复杂。虽然我们正在简化,但依赖于RcppArmadillo
不是必需的,因为我们可以使用 pureRcpp
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector pure_rcpp_sum (NumericVector y, int n){
NumericVector x(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < y.size(); ++j) {
if (i != j) {
x[i] += y[j];
}
}
}
return x;
}
验证输出:
all.equal(as.vector(rcpp_sum(y, n)), x)
[1] TRUE
all.equal(pure_rcpp_sum(y, n), x)
[1] TRUE
更新
根据 OP 的要求,我们R
为此特定目的提供了一种优化的方法。上面演示了如何解决一个非常具体的问题,即只对向量中的值求和,而在C++
. 这本质上是教学性的,不一定是完成这项特定任务的最佳方式(如下所示)。
在我们展示简单的R
代码之前,我想指出,OP 担心在内部循环中有一个简单的条件语句是C++
不应该担心的(就像在 base 中的情况一样R
)。据我所知,在 OP 的链接中展示的子集是 O(n) 并且具有额外逻辑向量的额外开销。我们上面提出的解决方案应该更有效,因为它基本上可以在没有额外对象的情况下做同样的事情。
现在,对于更新的代码:
baseR <- function(y, n) {
mySum <- sum(y)
vapply(1:n, function(x) mySum - y[x], FUN.VALUE = 1)
}
## Here is the OP code for reference
OP <- function(y, n) {
x <- rep(NA, n)
for(i in 1:n) {x[i] <- sum(y[-i])}
x
}
而已。它也快如闪电:
huge_y <- rnorm(1e6)
huge_n <- 1e3
system.time(t1 <- baseR(huge_y, huge_n))
user system elapsed
0.003 0.000 0.003
system.time(t2 <- pure_rcpp_sum(huge_y, huge_n))
user system elapsed
2.776 0.003 2.779
system.time(t3 <- OP(huge_y, huge_n))
user system elapsed
9.555 1.248 10.805
all.equal(t1, t2)
[1] TRUE
all.equal(t1, t3)
[1] TRUE