Eg: 2,3,4,5,6.
The expected output should be 2.
How can I write comparator func for min_element func to get the smallest even number.
auto mini_even=*min_element(vec.begin(),vec.end(),cmp);
CodePudding user response:
You can use a comparator that puts all even numbers before odd ones, ie any even number compares less than any odd, while all other comparisons are as usual:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> vec{1,2,3};
auto cmp = [](int a,int b){
if (a%2 == b%2) return a < b;
if (a%2) return false; // a odd b even
return true; // a even b odd
};
auto mini_even=*min_element(vec.begin(),vec.end(),cmp);
std::cout << mini_even;
}
To handle the case of a vector that only contains odd numbers you should check if the result is even or not.
The same effect can be achieved with a more elegant way of defining the comparator, as suggested by Jarod42 in a comment:
const auto projection = [](int n) { return std::make_pair(is_odd(n), n); }; const auto comp = [=](int lhs, int rhs){ return projection (lhs) < projection (rhs); };
std::pair
s have an operator<
that will, same as the above, place all even numbers (the ones where is_odd
is false
) before the odd ones.
And if you want to follow common practice to return vec.end()
when the desired element cannot be found, you can wrap it in a function:
template <typename IT>
IT min_even(IT first, IT last) {
if (first == last) return last;
auto cmp = .... see above ...
auto it = min_element(first,last,cmp);
if (*it % 2) return last;
return it;
}
Which can be generalized to work for any predicate:
template <typename IT, typename Predicate>
IT min_proj(IT first,IT last,Predicate pred){
if (first == last) return last;
const auto projection = [pred](int n) { return std::make_pair(!pred(n), n); };
const auto cmp = [=](int lhs, int rhs){ return projection (lhs) < projection (rhs); };
auto it = min_element(first,last,cmp);
if (!pred(*it)) return last;
return it;
}