Reputation: 212
I'm trying to find the index of the last non-zero element in a std::vector<double>
. If the last element in the vector is non-zero then it should return the index of that last element.
I believe I can use std::find_if_not
, reverse iterators and std::distance
, based on this:
std::find_if_not(amounts.rbegin(), amounts.rend(), 0.0)
where amounts
is a std::vector<double>
, but I'm having difficulty in combining this with std::distance
and a forward iterator amounts.begin()
.
Also, is there a way I can introduce a predicate to compare on, say a tolerance of 1e-8?
I'm using C++11.
Upvotes: 2
Views: 3493
Reputation: 50016
Example:
std::vector<double> v{1.32, 1.423, 2.543, 3.534, 4.2, 0};
auto result1 = std::find_if(std::rbegin(v), std::rend(v), [](auto& v) { return std::fabs(v - 0) > std::numeric_limits<double>::epsilon(); } );
if (result1 != std::rend(v)) {
std::cout << *result1 << "\n";
std::cout << std::distance(std::begin(v), (result1 + 1).base());
}
outputs:
4.2
4
[edit]
more explanation on:
std::fabs(v - 0) > std::numeric_limits<double>::epsilon(); }
in OP question there was:
Also, is there a way I can introduce a predicate to compare on, say a tolerance of 1e-8?
so this is such tolerance check, you can replace epsilon
use with some other value.
Upvotes: 9
Reputation: 238401
but I'm having difficulty in combining this with std::distance and a forward iterator amounts.begin()
Reverse iterators have member function base
that returns a non-reverse iterator with the relation &*(rit.base() - 1) == &*rit
. So, you can use the following:
std::distance(amounts.begin(), found.base()) - 1;
Another option:
amounts.size() - std::distance(amounts.rbegin(), found) - 1
Also, is there a way I can introduce a predicate to compare on, say a tolerance of 1e-8?
Yes. In fact, you must use a predicate, even for the exact comparison, since that's what std::find_if_not
expects as the third parameter (instead of value of an element).
Upvotes: 0
Reputation: 7220
A simple for
loop can also do the trick, see live sample: http://ideone.com/dVNOKk
#include <iostream>
#include <vector>
int main() {
std::vector<int> v{1, 2, 3, 4, 1, 2, 3, 0, 4, 1, 2, 3, 4, 0, 0, 0};
for (int i = static_cast<int>(v.size()) - 1; i >= 0; --i) {
if (v.at(i) != 0) {
std::cout << "Last non-zero at: " << i << '\n';
break;
}
}
return 0;
}
Output: Last non-zero at: 12
Upvotes: 0