How to tell C ++ to discard a specific element in a vector according to index pointer

I am using RCPP to speed up R code in my project. Now I am doing a translation of my R code in C ++ using the Armadillo package. I found that I often write multiple lines in C ++ to replace one line in R ...

Here is my question: I have a vector of saved data: data. In addition, I have a matrix that stores the index of the elements I need to get. Let me first illustrate my script in R:

> Data
[1] 4 5 6 7 8

and

> index
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    1    0    0
[3,]    2    0    2

For each row of the "index" matrix, I want to get the corresponding elements from the data. In R, I only need to enter the following code:

> Data[index[1,]]
[1] 4 5 6

> Data[index[2,]]
[1] 4

> Data[index[3,]]
[1] 5 5

i.e. the elements that I need from the first row of the "index" matrix are Data [1], Data [2], Data [3]

, , [1]

, "index", [2] [2]

R , R 0 "" .

'Data' '' index ' C . , , R ? !

+4
3

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 NA Data vector

apply Rcpp ,

[: article RCpp

: mysubset.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
+1

++ , :

#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;
}
+1

, , :

, (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


Theoretically, you will need an algorithm that does something like std::transform_if. But this does not exist. See Why is there no transform_if in the C ++ Standard Library?

+1
source

Source: https://habr.com/ru/post/1692475/


All Articles