|
Prev: Wanna do a WriteLongwordBits contest ? (Skybuck's SimInt64 C/C++ version)
Next: Callback function and templates
From: Gerhard Wolf on 7 May 2008 05:39 Jerry Coffin schrieb: > In article <68adjjF2shlgaU1(a)mid.individual.net>, quisquiliae(a)gmx.de > says... >> Hi, >> >> i have to vectors. >> std::vector<double> a; >> std::vector<double> b; >> same type, size and have synchronous value pairs. The values in "a" are >> decimal time values (linear increasing). >> >> Now i want to copy in a 3rd vector "c" all elements from a start value >> to a end value. My first idea was something like: >> >> std::vector<double> c; // target >> for (std::vector<double>::iterator it=a.begin(); it != a.end(); it++) { >> if (*it > startvalue && *it < endvalue) { >> c.push_back(?); >> } >> } >> >> do i need a 2nd iterator for vector b !? but how? >> or ist there a easier was to get the values to vector c? > > As I understand it, you want to take all the values that are in a or b > that fall within some specified range, and copy them into c. > > If that's the case, one method would be something like this: > > template <class T> > class out_of_range { > T lower_; > T upper_; > public: > out_of_range(T const &lower, T const &upper) : > lower_(lower), upper_(upper) > {} > > bool operator()(T const &value) { > return std::less(value, lower) || std::less(upper, value); > } > }; > > std::remove_copy_if(a.begin(), > a.end(), > std::back_inserter(c), > out_of_range(startvalue, endvalue)); > > std::remove_copy_if(b.begin(), > b.end(), > std::back_inserter(c) > out_of_range(startvalue, endvalue)); > > If there are likely to be a lot of values outside the specified range, > this isn't very efficient. In such a case, it's faster to use a binary > search to find your two end-points, and then copy everything in-between: > > std::vector<double>::iterator start, stop; > > start = std::lower_bound(a.begin(), a.end(), startvalue); > stop = std::upper_bound(a.begin(), a.end(), endvalue); > > std::copy(start, stop, std::back_inserter(c)); > > start = std::lower_bound(b.begin(), b.end(), startvalue); > stop = std::upper_bound(b.begin(), b.end(), endvalue); > > std::copy(start, stop, std::back_inserter(c)); > > Note that this produces all the elements from a before any of the > elements from b. If you want then in order instead, you have a couple of > choices. One is to just sort c after doing the above. Another is to > merge the ranges instead of just copying the items one after the other: > > starta = std::lower_bound(a.begin(), a.end(), startvalue); > stopa = std::upper_bound(a.begin(), a.end(), endvalue); > > startb = std::lower_bound(a.begin(), a.end(), startvalue); > stopb = std::lower_bound(a.begin(), a.end(), endvalue); > > std::merge(starta, stopa, startb, stopb, std::back_inserter(c)); > Thanks. For the moment it works using an index. So i have some time to analyse and test your tips and replace the code. |