views:

76

answers:

2

Hi,

I'm tring to calculate the standard deviation of a vector of doubles (called A). Now I have a function called StDev that will do this. However, the first few elements of vector A are zero and I need to remove these. To do this I create a sub-array and then pass this to my StDev function as follows:

 std::vector<double> Array(find_if(Data.begin(), Data.end(), std::bind1st (std::not_equal_to<double>(), 0.0)), Data.end());     

 double standard_deviation = StDev(Array); 

Is there a way of doing this without having to create the vector 'Array' which is only used once. Can I somehow pass the required sub-array directly?

Thanks!

+5  A: 

If you can modify your StDev function to take an iterator range instead of a whole container, you can do this quite easily:

template <typename ForwardIt>
std::iterator_traits<ForwardIt>::value_type 
StDev(ForwardIt first, ForwardIt last) { /* ... */ }

// called as:
double stdev = StDev(Data.begin(), Data.end());

// or:
double stdev = StDev(
    find_if(Data.begin(), Data.end(), 
            std::bind1st(std::not_equal_to<double>(), 0.0)), 
    Data.end()); 
James McNellis
Nice and instructive answer !
Cedric H.
Ideally I'd like to avoid re-writting my StDev function.
Wawel100
@Wawel100: "Can I somehow pass the required sub-array directly?" => Yes, use what James McNellis suggested. This is by far the most flexible and efficient solution.
ereOn
@Wawel100: This doesn't really require a whole lot of changes: you just have to use `first` and `last` instead of `c.begin()` and `c.end()` inside of the new `StDev()` function. You can keep your existing `StDev()` function and create a new `StDevRange()` function template if you'd prefer (`StDev()` could then be implemented in terms of `StDevRange()`. This would keep you from having to change all the places that call `StDev()`, but really, that probably isn't too large a task).
James McNellis
I've implemented your solution as an alternative I guess I could also pass a tempory object (?): double standard_deviation = StDev(std::vector<double>(find_if (Data.begin(), Data.end(), std::bind1st (std::not_equal_to<double>(), 0.0)), Data.end()));
Wawel100
+1  A: 

You could change your StDev function so that it skips however many elements at the start of the array that are zero.

bde