c++c++11stdlist

Find all matching elements in std::list


I was wondering if there's any built-in or well-established way (i.e. via lambda) to go through the elements of an std::list and find all the ones that match a given value? I know I can iterate through all of them, but I thought I'd ask if there's a way to get an iterator that iterates through just the elements that match a given criteria? My sample below only gives me the iterator to 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.


Solution

  • std::find_if is a generalisation of std::find for when you need a function to check for the elements you want, rather than a simple test for equality. If you just want to do a simple test for equality then there's no need for the generalised form, and the lambda just adds 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 rather than calling find in a loop I'd just write the loop manually:

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