Search code examples
c++c++11findstl-algorithm

Find the nth element satisfying a condition?


Is there a couple of std::algorithm/lambda function to access the nth element satisfying a given condition. Because std::find_if will access the first one, so is there an equivalend to find the nth one ?


Solution

  • You need to create a stateful predicate that will count the number of instances and then complete when the expected count is reached. Now the problem is that there are no guarantees as of how many times the predicate will be copied during the evaluation of the algorithm, so you need to maintain that state outside of the predicate itself, which makes it a bit ugly, but you can do:

    iterator which;
    {  // block to limit the scope of the otherwise unneeded count variable
       int count = 0;
       which = std::find_if(c.begin(), c.end(), [&count](T const & x) {
            return (condition(x) && ++count == 6)
       });
    };
    

    If this comes up frequently, and you are not concerned about performance, you could write a predicate adapter that created a shared_ptr to the count internally and updated it. Multiple copies of the same adapter would share the same actual count object.

    Another alternative would be to implement find_nth_if, which could be simpler.

    #include <iterator>
    #include <algorithm>
    
    template<typename Iterator, typename Pred, typename Counter>
    Iterator find_if_nth( Iterator first, Iterator last, Pred closure, Counter n ) {
      typedef typename std::iterator_traits<Iterator>::reference Tref;
      return std::find_if(first, last, [&](Tref x) {
        return closure(x) && !(--n);
      });
    }
    

    http://ideone.com/EZLLdL