62

Is there a find() function for list as there was in vector?

Is there a way to do that in list?

mtb
  • 1,350
  • 16
  • 32
Prasanth Madhavan
  • 12,657
  • 15
  • 62
  • 94
  • 3
    `std::vector` has a `find()` method? That's news to me. – Frerich Raabe Jan 05 '11 at 12:58
  • mybad... i meant fint(vectoriterator.begin(),vectoriterator.end(),string) – Prasanth Madhavan Jan 05 '11 at 13:10
  • 3
    You are correct, `std::vector` does not have a `find()` method. – Raedwald Jan 05 '11 at 13:11
  • For large sorted lists, binary_search is more efficient. – Marc Butler Jan 05 '11 at 13:31
  • @Marc: lists allow random access already, did I miss something? – Roman L Jan 05 '11 at 14:07
  • @7vies The binary search is optimal log(n) for sorted data. I'm not sure what point you are making. – Marc Butler Jan 05 '11 at 15:22
  • 1
    @Marc: binary search requires random access, which lists don't allow (we are talking about STL list here, so it is a linked list not something like ArrayList) – Roman L Jan 05 '11 at 15:30
  • @7vies Sorry. Right you are -- my mistake. However, it looks like the STL lower_bound algorithm can be used. – Marc Butler Jan 05 '11 at 15:43
  • @Marc: yes, but it will still be relatively inefficient. The comparison will only be invoked O(log N) times, but stepping through the iterators will take O(N). – Matthieu M. Jan 05 '11 at 16:43
  • @Prasanth: if possible, stay away from `std::list` unless your container requirements dictate that you should use it. It's the most space inefficient container available in the STL (for a linear container, that is) and iteration is painfully slow. – Matthieu M. Jan 05 '11 at 16:46
  • @Matthieu Agreed, but I think still more efficient than plain find(). Though I doubt it is worth while for small amounts of data. – Marc Butler Jan 05 '11 at 17:34
  • 1
    @Marc: actually it's especially worthwile for complicated `operator<` the cost of a branch pales before the cost of a memory access. – Matthieu M. Jan 05 '11 at 21:09

5 Answers5

111

You use std::find from <algorithm>, which works equally well for std::list and std::vector. std::vector does not have its own search/find function.

#include <list>
#include <algorithm>

int main()
{
    std::list<int> ilist;
    ilist.push_back(1);
    ilist.push_back(2);
    ilist.push_back(3);

    std::list<int>::iterator findIter = std::find(ilist.begin(), ilist.end(), 1);
}

Note that this works for built-in types like int as well as standard library types like std::string by default because they have operator== provided for them. If you are using using std::find on a container of a user-defined type, you should overload operator== to allow std::find to work properly - see EqualityComparable concept.

wkl
  • 77,184
  • 16
  • 165
  • 176
  • What's the time complexity of `std::find()` ? Perhaps, O(n) ? – Sungguk Lim Dec 03 '14 at 13:13
  • 3
    No binary seach capabilities for a sorted container? Lazy implementation. – LDS May 07 '15 at 15:26
  • 4
    @LDS - `std::binary_search` provides binary searches. – wkl May 07 '15 at 15:31
  • string has the find series functions. Not sure other containers do not. – Kemin Zhou Jul 26 '17 at 02:20
  • `std::binary_search` only returns `true` or `false`. I think the OP may be interested in `LB = std::lower_bound(v.begin(),v.end(),value)`. Then `LB` is an iterator to the first element >= `value` we look for. Iff `*LB==value`, then `LB - v.begin()` is the index of `value`. – Max Feb 03 '19 at 05:02
  • I would like to add that when one use find, the type of the container element and the type of the val to search does not need to match! The only thing is the the operator== of the container elements need to be defined for the type of the val to search. Might be useful sometimes... – David Daverio Mar 15 '21 at 00:05
23

No, not directly in the std::list template itself. You can however use std::find algorithm like that:

std::list<int> my_list;
//...
int some_value = 12;
std::list<int>::iterator iter = std::find (my_list.begin(), my_list.end(), some_value);
// now variable iter either represents valid iterator pointing to the found element,
// or it will be equal to my_list.end()
Ajay
  • 18,086
  • 12
  • 59
  • 105
Jan Holecek
  • 2,131
  • 1
  • 16
  • 26
20

Besides using std::find (from algorithm), you can also use std::find_if (which is, IMO, better than std::find), or other find algorithm from this list


#include <list>
#include <algorithm>
#include <iostream>

int main()
{
    std::list<int> myList{ 5, 19, 34, 3, 33 };
    

    auto it = std::find_if( std::begin( myList ),
                            std::end( myList ),
                            [&]( const int v ){ return 0 == ( v % 17 ); } );
        
    if ( myList.end() == it )
    {
        std::cout << "item not found" << std::endl;
    }
    else
    {
        const int pos = std::distance( myList.begin(), it ) + 1;
        std::cout << "item divisible by 17 found at position " << pos << std::endl;
    }
}
Ajay
  • 18,086
  • 12
  • 59
  • 105
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • Why is find_if better? If you are searching for an element that matches with equality, are you saying you would not use find and would use find_if instead? find_if does allow you custom searching, but if you had to fit in some horrible functor to search for equals it would make code look very ugly compared to using find. – CashCow Dec 28 '12 at 12:06
  • 1
    @CashCow It all depends on what type of element is in the vector or list. Sometimes it is not possible to use std::find. – BЈовић Jan 06 '13 at 12:15
  • Yes, sometimes you need find_if which is why it is part of the library but that doesn't make it "better" such that you would use it even when std::find works. – CashCow Jan 07 '13 at 09:49
  • 1
    +1 if you already have an unary predicate, find_if is better. – Wolf Feb 26 '14 at 15:20
  • Maybe you should add a little example to **show the advantage**? – Wolf Feb 26 '14 at 15:24
  • @Wolf Thank you. That is what was missing. Added example now – BЈовић Feb 26 '14 at 15:31
  • Ok, that's an advanced example that requires C++11, well? – Wolf Feb 26 '14 at 15:33
  • @Wolf Yes. c++11 makes that example a bit simpler. But it is not that hard to convert it to a c++03 example – BЈовић Feb 26 '14 at 15:35
  • Yes, but maybe it should mentioned that this is C++11 code. ...and maybe using `==` for implementing predicate isn't such a good reason ;) – Wolf Feb 26 '14 at 15:39
  • @Wolf The example is very simple to demonstrate the idea. It is possible to implement something quite complex, that is why `find_if` may be better. – BЈовић Feb 26 '14 at 15:43
  • I mean, you demonstrate that `find_if` is better with a use case where `find` already works well. If the predicate was *divisible by 11* instead, the advantage of `find_if` would be obvious. – Wolf Feb 26 '14 at 16:45
3

What you can do and what you should do are different matters.

If the list is very short, or you are only ever going to call find once then use the linear approach above.

However linear-search is one of the biggest evils I find in slow code, and consider using an ordered collection (set or multiset if you allow duplicates). If you need to keep a list for other reasons eg using an LRU technique or you need to maintain the insertion order or some other order, create an index for it. You can actually do that using a std::set of the list iterators (or multiset) although you need to maintain this any time your list is modified.

CashCow
  • 30,981
  • 5
  • 61
  • 92
0

No, find() method is not a member of std::list. Instead, use std::find from <algorithm>

    std :: list < int > l;
    std :: list < int > :: iterator pos;

    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    l.push_back(4);
    l.push_back(5);
    l.push_back(6);

    int elem = 3;   
    pos = find(l.begin() , l.end() , elem);
    if(pos != l.end() )
        std :: cout << "Element is present. "<<std :: endl;
    else
        std :: cout << "Element is not present. "<<std :: endl;
talekeDskobeDa
  • 372
  • 2
  • 13
DecPK
  • 24,537
  • 6
  • 26
  • 42