I'm looking into using some C++ for simple parts of my R package using the Rcpp
package. I'm a C++ novice (but keen to learn!). I've implemented a few simple cpp programs using the excellent Rcpp
- in fact that package has motivated me to learn C++...
Anyway, I've got stuck with a simple problem, which if I can fix would help lots. I have a NumericVector
I want to subset and then sort. The code below sorts the whole vector (and would also deal with NAs, which is what I need).
My question is, say I want to extract a part of this vector, sort and have it available for other processing - how can I do that? For example, for a vector of length 10, how do I extract and sort the elements 5:10?
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
RcppExport SEXP rollP(SEXP x) {
NumericVector A(x); // the data
A = sort_unique(A);
return A;
}
which I call from R:
sourceCpp( "rollP.cpp")
rollP(10:1)
# [1] 1 2 3 4 5 6 7 8 9 10
Sorting a vector in C++ can be done by using std::sort(). It is defined in<algorithm> header. To get a stable sort std::stable_sort is used. It is exactly like sort() but maintains the relative order of equal elements.
A vector in C++ can be easily sorted in ascending order using the sort() function defined in the algorithm header file. The sort() function sorts a given data structure and does not return anything. The sorting takes place between the two passed iterators or positions.
In this type of sorting 2D vector is entirely sorted on basis of a chosen column. For example, if the chosen column is second, the row with the smallest value in the second column becomes the first row, the second smallest value in the second column becomes the second row, and so on.
Here are 3 variants:
include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector rollP(NumericVector A, int start, int end) {
NumericVector B(end-start+1) ;
std::copy( A.begin() + start-1, A.begin() + end, B.begin() ) ;
return B.sort() ;
}
// [[Rcpp::export]]
NumericVector rollP2(NumericVector A, int start, int end) {
NumericVector B( A.begin() + start-1, A.begin() + end ) ;
return B.sort() ;
}
// [[Rcpp::export]]
NumericVector rollP3(NumericVector A, int start, int end) {
NumericVector B = A[seq(start-1, end-1)] ;
return B.sort() ;
}
start
and end
are meant as 1-based indices, as if you were passing A[start:end]
from R
.
You need to look into C++ indexing, iterators and the whole bit. At a minimum, you need to change your interface (vector, fromInd, toInd) and figure out what you want to return.
One interpretation of your question would be to copy the subset from [fromInd, toInd)
into a new vector, sort it and return it. All that is standard C++ fare, and a good text like the excellent (and free!!) C++ Annotations will be of help. It has a pretty strong STL section too.
You can use std::slice
on a std::valarray
. But if you want to use std::vector
specifically then you can use std::copy
to extract a portion of the vector and then use std::sort
to sort the extracted slice of the vector.
You can do this quite easily by using the std::sort
implementation that receives two iterators:
#include <vector>
#include <cinttypes>
#include <algorithm>
template <typename SeqContainer>
SeqContainer slicesort(SeqContainer const& sq, size_t begin, size_t end) {
auto const b = std::begin(sq)+begin;
auto const e = std::begin(sq)+end;
if (b <= std::end(sq) && e <= std::end(sq)) {
SeqContainer copy(b,e);
std::sort(copy.begin(),copy.end());
return copy;
}
return SeqContainer();
}
Which can be invoked like
std::vector<int> v = {3,1,7,3,6,-2,-8,-7,-1,-4,2,3,9};
std::vector<int> v2 = slicesort(v,5,10);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With