I'd like to use boost::range to pull off something similar to the "fancy indexing" available in NumPy and Matlab. Specifically, I would like to select certain elements of one indexable container using elements of another container as the indices. For example, one can do the following in Python:
>>> squares = numpy.arange(10)**2 # Step 1 - setup squares
>>> indices = numpy.array([1,3,4]) # Step 2 - setup indices
>>> squares[indices] # Step 3 - fancy indexing
array([ 1, 9, 16])
In C++, using boost::range, I think the above code would look something like this:
#include "sampled.hpp"
#include <boost/assign/std/vector.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/counting_range.hpp>
#include <iostream>
#include <vector>
using namespace boost;
using namespace boost::adaptors;
using namespace boost::assign;
using namespace boost::lambda;
using namespace std;
int main(int argc, char** argv)
{
// Step 1 - setup squares
vector<int> squares;
push_back(
squares,
counting_range(1,11) | transformed(ret<int>(_1 * _1))
);
// Step 2 - setup indices
vector<size_t> indices;
indices += 1,3,4;
// Step 3 - fancy indexing
for_each(
squares | sampled(indices),
cout << _1 << constant(" ")
);
return 0;
}
Since the name "indexed" is already used by an existing range adaptor (boost::adaptor::indexed), I called the yet-unimplemented indexing adaptor "sampled" in the above code.
Does anyone know if such an adaptor already exists in boost somewhere, or have an implementation they'd be willing to share? I've started trying to implement it myself by first writing a "sampled_iterator" (using iterator_adaptor) and then a "sampled_range" (using iterator_range) but I'm finding it quite tricky.