简体   繁体   中英

C++ std::find_if on iterator in reverse order

In the following code, is there an elegant way to find it_end ?

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <type_traits>

template <class Iterator, class U = typename std::iterator_traits<Iterator>::value_type>
void process(Iterator begin, Iterator end)
{
    // first nonzero
    auto it_begin = std::find_if(begin, end, [](U val){return val != 0;});

    // end of nonzero values
    int n = std::distance(begin, end);
    int index = n-1;
    for(int i=n-1; i>=0; --i) {
        if(*(begin+i) == 0) {
            index = i;
        } else {
            break;
        }
    }
    auto it_end = begin;
    std::advance(it_end, index);
    // ******* is there a way to use std::find_if or similar function to get it_end? *******

    for(auto it=it_begin; it!=it_end; ++it) {
        // a whole bunch of things
        // ...
        std::cout << *it << std::endl;
    }
}


int main()
{
    std::vector<int> v{0,0,1,2,3,0,0};

    process(v.begin(), v.end());
}

use std::reverse_iterator.

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <type_traits>
#include <list>

template <class Iterator, class U = typename std::iterator_traits<Iterator>::value_type>
void process(Iterator begin, Iterator end)
{
    // first nonzero
    auto it_begin = std::find_if(begin, end, [](U val){return val != 0;});
    if (it_begin == end) 
        return; // all value is zeros. 

    // reverser iterator
    auto r_begin = std::reverse_iterator(end);
    auto r_end = std::reverse_iterator(it_begin);
    auto r_find = std::find_if(r_begin, r_end, [](U val) { return val != 0; });
    auto it_end = r_find.base();

    
    for(auto it = it_begin; it != it_end; ++it) {
        std::cout << *it << std::endl;
    }
}


int main()
{
    std::list<int> v{0,0,0,2,0,3,4};
    process(v.begin(), v.end());
}

You can use the reverse iterator .

My implementation:

template <class Iterator, class U = typename std::iterator_traits<Iterator>::value_type>
void yet_another_process(Iterator begin, Iterator end, std::reverse_iterator<Iterator> rbegin, std::reverse_iterator<Iterator> rend) {
    auto it_begin = std::find_if(begin, end, [](U val) { return val != 0; });
    auto it_end = std::find_if(rbegin, rend, [](U val) { return val != 0; }).base();    // Notice this base()
    for (auto it = it_begin; it != it_end; ++it) {
        std::cout << *it << std::endl;
    }
}

and in main() :

int main() {
    std::vector<int> v { 0, 0, 1, 2, 3, 0, 0 };
    yet_another_process(v.begin(), v.end(), v.rbegin(), v.rend());
}

The base() method of a reverse iterator returns the underlying "normal" iterator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM