I would like to know how can I find the index positions of elements that verify a certain condition (for example greater than). For example if I have a vector of int values
vector<int> V;
V contains the values 3 2 5 8 2 1 10 4 7
and I want to get all the index positions of elements that are greater than 5.
I know std::find_if
but according to the documentation it just finds the first element that satisfies a condition.
Loop std::find_if
, starting from where you stopped last time.
Sample (see it work):
std::vector<size_t> results;
auto it = std::find_if(std::begin(v), std::end(v), [](int i){return i > 5;});
while (it != std::end(v)) {
results.emplace_back(std::distance(std::begin(v), it));
it = std::find_if(std::next(it), std::end(v), [](int i){return i > 5;});
}
First we set up the iterator with the first result. If it's not found, the while loop never executes. Otherwise, the index position is stored (std::distance
is basically a more generic it - std::begin(v)
), and the search continues onward.
I think I'd use std::copy_if
:
std::vector<int> x{3, 2, 5, 8, 2, 1, 10, 4, 7};
std::vector<size_t> y(x.size());
std::iota(y.begin(), y.end(), 0);
std::copy_if(y.begin(), y.end(),
std::ostream_iterator<size_t>(std::cout, " "),
[=](size_t i) { return x[i] > 5; });
For me, this gives 3 6 8
, the indices of 8, 10 and 7 in x
-- exactly what we want.
If you're stuck with a C++98/03 compiler/library, you'll use std::remove_copy_if
instead (and reverse the sense of the comparison). In this case, you obviously won't be able to use a lambda for the comparison either.
Just for fun, transform_if
algorithm:
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>
template<typename InputIterator, typename OutputIterator,
typename UnaryPredicate, typename UnaryFunction>
OutputIterator
transform_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred,
UnaryFunction func)
{
for (; first != last; ++first, ++result)
if (pred(*first))
*result = func(*first);
return result;
}
int main()
{
std::vector<int> x {3, 2, 5, 8, 2, 1, 10, 4, 7};
std::vector<size_t> indices;
size_t index = 0;
transform_if(x.begin(), x.end(), std::back_inserter(indices),
[&](int i){ return ++index, i > 5; },
[&](int){ return index-1; });
std::copy(indices.begin(), indices.end(),
std::ostream_iterator<size_t>(std::cout, " "));
}
Output: 3 6 8