如何根据指数指标告诉C++放弃矢量中的某些元素
how to tell C++ to abandon certain element in vector according to an index indicator
我正在使用RCPP来加速项目中的R代码。现在我正在做的是使用犰狳包将我的 R 代码传输到C++。我发现我经常用C++写多行来替换 R 中的一行......
这是我的问题: 我有一个向量存储的数据:数据。我还有一个矩阵,存储了我需要访问的元素索引。请允许我先在 R 中说明我的场景:
> Data
[1] 4 5 6 7 8
和
> index
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 0 0
[3,] 2 0 2
对于"索引"矩阵的每一行,我想从数据中获取相应的元素。在 R 中,我只需要像这样编码:
> Data[index[1,]]
[1] 4 5 6
> Data[index[2,]]
[1] 4
> Data[index[3,]]
[1] 5 5
即 我需要从"索引"矩阵的第一行中的元素是数据[1],数据[2],数据[3]
我需要从"索引"矩阵的第二行中的元素是 数据[1]
我需要从"索引"矩阵的第 3 行获得的元素是 数据[2] 数据[2]
R 的便利之处在于 R 会自动将 0 索引标识为"无"并且不会访问它。
现在我把向量"数据"和矩阵"索引"输入到C中。我想知道有没有办法达到与上述 R 类似的结果?多谢!
Base R
您可以使用索引对数据进行子集化,结果将是一个列表
Data <- c( 4 ,5 ,6, 7, 8)
index <- matrix(c(1,2,3, 1, 0, 0, 2,0,2), byrow = TRUE, nrow = 3)
apply(index, 1, function(x) Data[x])
# [[1]]
# [1] 4 5 6
#
# [[2]]
# [1] 4
#
# [[3]]
# [1] 5 5
结果将是矩阵
index <- matrix(c(1,2,3, 1, 0, 0, 2,0,2), byrow = TRUE, nrow = 3)
index[index == 0] <- NA
index
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 1 NA NA
# [3,] 2 NA 2
apply(index, 2, function(x) Data[x])
# [,1] [,2] [,3]
# [1,] 4 5 6
# [2,] 4 NA NA
# [3,] 5 NA 5
使用[
:
matrix( Data[index], nrow = 3, byrow = FALSE) # another way to get the same matrix
Rcpp:对于 0 索引,在Data
向量中使用 NA
您只需按照此处所述将apply
转换为Rcpp
代码
或
使用[
:有关使用 RCpp 进行向量子集的更多信息,请参阅本文
文件:我的子集.cpp
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector mysubset(NumericVector Data, NumericVector index) {
return Data[index];
}
RStudio:
library('Rcpp')
sourceCpp("mysubset.cpp")
Data <- c( NA, 4 ,5 ,6, 7, 8) # for 0 index, use NA
index <- matrix(c(1,2,3, 1, 0, 0, 2,0,2), byrow = TRUE, nrow = 3)
matrix( mysubset(Data, index), nrow = 3, byrow = FALSE)
# [,1] [,2] [,3]
# [1,] 4 5 6
# [2,] 4 NA NA
# [3,] 5 NA 5
mysubset(Data, index[1,])
# [1] 4 5 6
na.omit(mysubset(Data, index[2,]))
# [1] 4
在C++中,有一些工作要做,但这是可行的:
#include <type_traits>
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <utility>
template <typename T, typename I,
typename std::enable_if<std::is_convertible<I,
typename std::vector<T>::size_type>::value>::type* = nullptr>
std::vector<std::vector<T>> product (const std::vector<T>& data,
const std::vector<std::vector<I>>& index) {
std::vector<std::vector<T>> result (index.size());
std::transform(std::begin(index),
std::end(index),
std::make_move_iterator(std::begin(result)),
[&data, &filler](const std::vector<I>& index_row) {
std::vector<T> row;
for (auto& pos : index_row) {
if (pos > 0) {
row.push_back(data.at(pos - 1));
}
}
return row;
});
return result;
}
现在演示一下它是如何工作的:
auto main() -> int {
std::vector<int> data = {4, 5, 6, 7, 8};
std::vector<std::vector<int>> index = {
{1, 2, 3},
{1, 0, 0},
{2, 0, 2}
};
std::vector<std::vector<int>> result = std::move(product(data, index));
std::cout << result << "n";
}
输出
4,5,6,
4,
5,5,
演示中使用的帮助程序函数:
template <typename T>
std::ostream& operator << (std::ostream& oss, const std::vector<T>& v) {
for (auto &item : v) {
oss << item << ",";
}
return oss;
}
template <typename T>
std::ostream& operator << (std::ostream& oss, const std::vector<std::vector<T>>& vv) {
for (auto &v : vv) {
oss << v << "n";
}
return oss;
}
如果你想让事情变得简单,那么我推荐以下几点:
假设您有一个数据向量 (Data
):
std::vector<int> Data{ 4, 5, 6, 7, 8 };
和一个索引映射,它是列向量的行主序向量(index
):
std::vector<std::vector<int>> index{ {1, 2, 3}, {1, 0, 0}, {2, 0, 2} };
那么下面的代码,将取一行index
的索引。获取Data
的索引元素并将其追加到结果向量,但索引为 0(或越界)除外:
std::vector<int> r;
for (auto i : index[1-1])
if (i > 0 && i <= Data.size())
r.push_back(Data[i-1]);
以下代码的输出
#include <vector>
#include <iostream>
std::vector<int> Data{ 4, 5, 6, 7, 8 };
std::vector<std::vector<int>> index{ {1, 2, 3}, {1, 0, 0}, {2, 0, 2} };
std::vector<int> r1, r2, r3;
for (auto i : index[1-1]) if (i > 0 && i <= Data.size()) r1.push_back(Data[i-1]);
for (auto i : index[2-1]) if (i > 0 && i <= Data.size()) r2.push_back(Data[i-1]);
for (auto i : index[3-1]) if (i > 0 && i <= Data.size()) r3.push_back(Data[i-1]);
for (auto d : r1) std::cout << d << " "; std::cout << std::endl;
for (auto d : r2) std::cout << d << " "; std::cout << std::endl;
for (auto d : r3) std::cout << d << " "; std::cout << std::endl;
是:
4 5 6
4
5 5
从理论上讲,您需要一种算法,例如std::transform_if
.但这并不存在。请参阅为什么C++标准库中没有transform_if?
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用strcpy将char数组的元素复制到另一个数组
- 使用不带参数的函数访问结构元素
- 给定n个元素的m个集合.在C++中找到出现在最大集合数中的元素
- C++如何通过用户输入删除列表元素
- lower_bound()返回最后一个元素
- 基于多个条件处理地图中的所有元素
- 调整大小后指向元素值的指针unordered_map有效?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 使用函数"remove"删除重复元素
- 具有最大子序列大小的序列,每个元素都相同
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将元素添加到数组的线程安全函数?
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 我想访问std::unique_ptr中的一个特定元素
- 如何通过 getter 函数删除矢量的元素?
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 从控制台中删除最后打印的元素
- 如何根据指数指标告诉C++放弃矢量中的某些元素