Find all matching items in std :: list

I was wondering if there is a built-in or well-established way (i.e. via lambda) to go through the std :: list elements and find all those that match the given value? I know that I can iterate over all of them, but I thought I would ask if there is a way to get an iterator that only executes those elements that match the given criteria? My example below gives me only an iterator for the first matching element.

#include <list> #include <algorithm> #include <stdio.h> int main() { std::list<int> List; List.push_back(100); List.push_back(200); List.push_back(300); List.push_back(100); int findValue = 100; auto it = std::find_if(List.begin(), List.end(), [findValue](const int value) { return (value == findValue); }); if (it != List.end()) { for (; it != List.end(); ++it) { printf("%d\n", * it); } } return 0; } 

Thanks for any feedback.

+6
source share
3 answers

std::find_if is a generalization of std::find when you need a function to check the elements you want, rather than a simple equality test. If you just want to do a simple equality test, then there is no need for a generalized form, and the lambda will just add complexity and verbosity. Just use std::find(begin, end, findValue) instead:

 std::vector<std::list<int>::const_iterator> matches; auto i = list.begin(), end = list.end(); while (i != end) { i = std::find(i, end, findValue); if (i != end) matches.push_back(i++); } 

But instead of calling find in a loop, I just write the loop manually:

 std::vector<std::list<int>::const_iterator> matches; for (auto i = list.begin(), toofar = l.end(); i != toofar; ++i) if (*i == findValue) matches.push_back(i); 
+7
source

boost::filter_iterator allows boost::filter_iterator to work only with iteration elements that satisfy the predicate. Given the Pred predicate and the Cont container,

 auto begin_iter = boost::make_filter_iterator(Pred, std::begin(Cont), std::end(Cont)); auto end_iter = boost::make_filter_iterator(Pred, std::end(Cont), std::end(Cont)); 

Now you can use begin_iter and end_iter as if they were iterators of the beginning and end of a container containing only those Cont elements that satisfied Pred . Another additional benefit is that you can wrap iterators in boost::iterator_range and use it in places that expect an iterable object, for example, based on the for range, do the following:

 auto range = boost::make_iterator_range(begin_iter, end_iter); for(auto x : range) do_something(x); 

Specifically, setting Pred to a functor (maybe a lambda) that checks for equality with your fixed value will give you the iterators you need.

+9
source

Using copy_if and iterators :

 #include <list> #include <algorithm> #include <iterator> #include <iostream> int main() { std::list<int> List; List.push_back(100); List.push_back(200); List.push_back(300); List.push_back(100); int findValue = 100; std::copy_if(List.begin(), List.end(), std::ostream_iterator<int>(std::cout, "\n"), [&](int v) { return v == findValue; }); return 0; } 

If you do not want to directly output the results and want to fill another container with matches:

 std::vector<int> matches; std::copy_if(List.begin(), List.end(), std::back_inserter(matches), [&](int v) { return v == findValue; }); 
+7
source

Source: https://habr.com/ru/post/979531/


All Articles