In comments to this question is-there-a-way-to-iterate-over-at-most-n-elements-using-range-based-for-loop there was additional question - is this possible to have "index view" on a container, i.e. to have subrange with some indexes filtered out.
Additionally I encountered a problem to find minimum value from a range with some indexes filtered out.
I.e. is it possible to replace such code as below with std and/or boost algorithms, filters - to make it more readable and maintainable:
template <typename Range, typename IndexPredicate>
auto findMin(const Range& range, IndexPredicate ipred)
-> boost::optional<typename Range::value_type>
{
bool found = false;
typename Range::value_type minValue{};
for (std::size_t i = 0; i < range.size(); ++i)
{
if (not ipred(i))
continue;
if (not found)
{
minValue = range[i];
found = true;
}
else if (minValue > range[i])
{
minValue = range[i];
}
}
if (found)
{
return minValue;
}
else
{
return boost::none;
}
}
Just to be used like this:
#include <iostream>
#include <vector>
int main() {
std::vector<float> ff = {1.2,-1.2,2.3,-2.3};
auto onlyEvenIndex = [](auto i){ return (i&1) == 0;};
auto minValue = findMin(ff, onlyEvenIndex);
std::cout << *minValue << std::endl;
}
Using the recently Standard range-v3 proposal:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<float> rng = {1.2,-1.2,2.3,-2.3};
auto even_indices =
ranges::view::iota(0ul, rng.size()) |
ranges::view::filter([](auto i) { return !(i & 1); })
;
auto min_ind = *ranges::min_element(
even_indices, [&rng](auto L, auto R) {
return rng[L] < rng[R];
});
std::cout << rng[min_ind];
}
Live Example. Note that the syntax is roughly similar to Boost.Range, but fully revamped to take advantage of C++14 (generalized lambdas, auto return type deduction etc.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With