tags:

views:

137

answers:

5

Hi Guys,

I'm trying to figure out the best C++ library/package for array manipulations in a manner of python. Basically I need a simplicity like this:

values  = numpy.array(inp.data)
idx1    = numpy.where(values > -2.14)
idx2    = numpy.where(values < 2.0)

res1 = (values[idx1] - diff1)/1000
res2 = (values[idx2] - diff2)*1000

In python it's just 5 lines, but the simplest way in C++ i can think of is quite a number of nested loops. Pls advise..

Basically my question is concerning the array/vector operations like array multiplications, operations on indexs, etc.. In the example above, res1 is an array, containing a set of elements filtered out of values array and some arithmetics applied afterward (subtraction, multiplication for all selected elements). In this python example I'm not copying elements of values array as it could be big enough in terms of memory, i'm keeping only the indexes and want to be able to run arithmetic operations on a selected set of elements of the original array.

+1  A: 

If I'm not mistaken, numpy is written mostly in C (with a Python wrapper), so you could be able to use it directly from C++ without much effort.

fortran
+4  A: 

I suggest you to check the algorithm header. Also don't work with arrays, you have std::vector or boost(soon to be std)::array.

wikipedia article

Reference for all algorithms

the_drow
+5  A: 

You should not be using arrays at all. Please sit down and learn about the std::vector class and about iterators and Standard Library algorithms. I strongly suggest reading the book The C++ Standard Library.

anon
+1 for mentioning such an excellent book
D.Shawley
What the poster calls "arrays" is not necessarily C arrays, it's the general concept.
static_rtti
@ static_rtti The term array in C++ has a specific technical meaning.
anon
+5  A: 

You can achieve something similar in C++ but you shouldn't use plain C arrays for it.

The easiest way I can see this work would be using a std::set of floats (your code looks like it assumes that the data is sorted in ascending order). You could also use a std::vector of float but you'll have to sort that yourself, probably by using std::sort.

In that case, your example code could look like this - the set assumes the values are unique, if they aren't, you could use a std::multiset instead;

std::set<float> values(inp.data.begin(), inp.data.end());
std::set<float>::iterator idx1 = values.lower_bound(-2.14);
std::set<float>::iterator idx2 = values.upper_bound(2.0);

float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;

Please note that the above code sample is not a 100% conversion of your original code - lower_boundgives you the first element that's equal or larger than -2.14. I also didn't put any checking code in for failures - if lower_bound or upper_bound can't find matching elements, they would return values.end(), for example.

Using vector, the example would look very similar, just one line more to pre-sort the vector:

std::vector<float> values(inp.data.begin(), inp.data.end());
std::sort(values.begin(), values.end();
std::vector<float>::iterator idx1 = std::lower_bound(values.begin(), values.end(), -2.14);
std::vector<float>::iterator idx2 = std::upper_bound(values.begin(), values.end(), 2.0);

float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;
Timo Geusch
This is really a good example, but not quite what i'm looking for. Basically in my python example res1 is also an array and the expression is a vector operation. This means that in C++ I have to put this whole thing in 2 loops like while(idx1 != values.end) { res1.push_back((*idx1 - diff1)/1000); }; while(idx2 != values.end) { res2.push_back((*idx2 - diff2)/1000); };
Linai
Ah, OK. I guess it would've helped if I spoke Python :).You could hide the loops using something like std::copy and copy them through a functor with a back inserter, but that's hiding the loop more than anything else.
Timo Geusch
+1  A: 

If you combine std::vector and boost::lambda, you can come really close to your example:

#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>

using boost::lambda::_1;

int main() {
    float ary[10] = { -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 };
    std::vector<float> v(&ary[0], &ary[10]);
    std::vector<float>::iterator iter1, iter2;

    iter1 = std::find_if(v.begin(), v.end(), (_1 > -2.14));
    iter2 = std::find_if(v.begin(), v.end(), (_1 < 2.0));

    // output:
    //     iter1 = -2.000
    //     iter2 = 1.000
    std::cout
        << "iter1 = " << *iter1 << "\n"
        << "iter2 = " << *iter2 << "\n"
        << std::endl;
    return 0;
}
D.Shawley
Same as above. This first part works fine, but what about vector operations like res_vector = (v[iter1] - fixed_value)*1000 ?
Linai
Only if by "really close" you mean "ten times more verbose" :)
static_rtti
@static_rtti: most of the verbosity is in the setup and printing. The python example omitted the `import numpy` and didn't include the printing. But yes, it is more verbose to include explicit typing and other static information. The core processing inside of `main` is pretty much the same though.
D.Shawley