C++ - Iterating over std::vector<> returned from find_if
Solution 1
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
bool IsOdd (int i) {
return ((i%2)==1);
}
int main () {
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "ODD values are: " << std::endl;
while(it != myvector.end() ){
std::cout << *it << " in position " << (it - myvector.begin()) << '\n';
it = std::find_if (++it, myvector.end(), IsOdd);
}
return 0;
}
EDIT: Changed it+1
to ++it
see @David Rodríguez - dribeas comment below.
Solution 2
You can increment it
and use it as a starting point to iterate further:
std::cout << "odd values: ";
auto it = myvector.begin();
while(it != myvector.end())
{
it = std::find_if (it, myvector.end(), IsOdd);
if(it == myvector.end()) break;
std::cout << *it << ' ';
++it;
}
std::cout << endl;
A much more algorithm oriented approach, makes use of copy_if
, having an output vector as a result container:
std::vector<int> results;
std::copy_if(myvector.begin(), myvector.end(), std::back_inserter(results), IsOdd);
Now results contains the odd values. (Note the back:inserter is in the <iterator>
header)
Solution 3
You can find the index of a vector iterator (and, more generally, any random-access iterator) by subtracting the start of the sequence:
std::cout << "The index is " << (it - myvector.begin()) << '\n';
Even more generally, there is a std::distance
function which can give you the distance between forward iterators. You could use that, for example, if your container were a list
; but you probably wouldn't want to, since it would be much slower.
To find all the odd numbers, you'll need a loop to call find
again, starting from the element after the one you just found.
Solution 4
You'll need a loop. The iterator-algorithm design of the standard library makes this pretty easy:
#include <iterator>
for (auto it = myvector.begin();
(it = std::find_if(it, myvector.end(), IsOdd)) != myvector.end(); )
{
std::cout << *it << " at index " << std::distance(myvector.begin(), it) << "\n";
}
Solution 5
Change these two lines:
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "The first odd value is " << *it << '\n';
into something like:
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
while ( it != myvector.end() ) {
std::cout << "The next odd value is " << *it << '\n';
it = std::find_if (++it, myvector.end(), IsOdd);
}
Comments
-
Brett almost 2 years
I'm learning C++, so I feel like this should be a very simple answer - but I can't seem to find it. So I apologize in advance if it's naive.
I have a
std::vector<int>
of of values, and I am trying to find the indices of the odd values.I am following the code from here:
(repeated below):
// find_if example #include <iostream> // std::cout #include <algorithm> // std::find_if #include <vector> // std::vector bool IsOdd (int i) { return ((i%2)==1); } int main () { std::vector<int> myvector; myvector.push_back(10); myvector.push_back(25); myvector.push_back(40); myvector.push_back(55); std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd); std::cout << "The first odd value is " << *it << '\n'; return 0; }
This example prints the first odd value. How could I extend this to give me the index values for each of the odd values in
myvector
? Is this the correct approach? -
Lightness Races in Orbit over 10 yearsTrolly challenge: can you make this work with a ranged-for? :)
-
Brett over 10 yearsI needed the info about the distance
(it - myvector.begin())
. Thanks! Reading this in full really helps my understanding. -
Kerrek SB over 10 years@LightnessRacesinOrbit: "Can I", or "Would I reccommend it"? :-)
-
David Rodríguez - dribeas over 10 yearsnit:
std::find_if(++it,...
-
wesley.mesquita over 10 years@DavidRodríguez-dribeas Sorry, but what is the advantage of
++
for this case? Is there any situation where the operator '+' is not overloaded? I did not get it. Thanks. -
David Rodríguez - dribeas over 10 years
it+1
requires random access iterators, that is a stronger requirement than++it
(requires only forward iterators). In this particular case it is fine, asstd::vector<>::iterator
are random access, but using++it
makes the solution feasible for other containers. -
Bill Door over 10 years
it - myvector.begin()
is also known asdistance(myvector.begin(), it)
.distance
might help to better understand what is happening. -
Bo R over 3 yearsYou can simplify the loop with
while(true)
. That way we don't check for end twice in every loop iteration.