1

Is there a way to find the minimum odd element of a vector of integers without basically reimplementing std::min_element and without doing additional work like computing the vector of odd integers first?

2
  • I honestly don't know why you got downvoted. Sure it's a quite trivial problem and could have a better title, but that asks for edit, not downvotes. Commented Jan 19, 2021 at 20:20
  • If you can, add a simple example with a comment that points where you would expect to put your condition. Commented Jan 19, 2021 at 20:23

4 Answers 4

4

While a custom comparison object suggested in another answer will be a simple solution for std::min_element (and similar) in particular, it won't work with all standard algorithms. A general approach that works with any standard algorithm is to define a custom iterator.

Customising, combining and extending standard algorithms can nearly always be achieved with iterators. Writing custom iterators from scratch involves a lot of boilerplate and unfortunately standard doesn't provide templates for many iterator adaptors. Boost does provide plenty of iterator adaptor templates, and in this case boost::filter_iterator should prove useful.


Instead of the more traditional iterator algorithms, you could use range algorithms instead.

Since C++20, there are a host of standard range adaptors for range algorithms which are easy to compose:

auto it = std::ranges::min_element( container | std::views::filter(condition) ); 

Note that at the moment of writing, only libstdc++ has implemented the ranges standard library.

Sign up to request clarification or add additional context in comments.

1 Comment

This would be great... (on my compiler at least) except that filtering the container creates a temporary vector which means that you get a dangling iterator back. The dandling iterator can't be used for anything.
3

A simple solution consists in using a custom comparator function with std::min_element.

What should be added in the following code is to check that the obtained value is odd indeed, as mentioned by @MSalters in their answer and by @Kevin in a comment.

#include <iostream> #include <algorithm> #include <vector> int main() { std::vector<int> v = {0, 3, 4, 1}; auto comp = [](int a, int b) { if ((a%2) and (b%2 == 0)) return true; if ((a%2 == 0) and (b%2)) return false; return a < b; }; auto min_odd = std::min_element(v.begin(), v.end(), comp); std::cout << *min_odd << std::endl; } 

2 Comments

Nitpick: This returns an iterator to the minimum even number if there are no odd numbers. It should probably return the end iterator. Not that that was one of the OP's requirements
@Kevin. Effectively. I completed the post
2

A C++20 solution:

std::vector<int> ints{0, 1, 2, 3, 4, 5}; auto odd = [](int i) { return bool(i % 2); }; auto e = std::ranges::min_element(ints | std::views::filter(odd)); 

Comments

1

Yes, that's not very hard. Implement a custom comparison that sorts each even element above all odd elements. You still need to sort the odd elements in their usual order, and at the end check that there was at least one odd element in the vector.

4 Comments

Why not simply using a custon comparator function with sd::min_element ?
Hmm, can you avoid to check parity of the current minimum for every single element?
@Damien: That's what I meant to write. A predicate is a unary function returning a boolean, but to sort two elements you need a comparator. (binary function returning a boolean)
Sorry, I misunderstood your post. I thought you wanted to sort the array first

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.