find in std::vector<std::pair>

26,780

Solution 1

A possible solution:

struct comp
{
    comp(std::string const& s) : _s(s) { }

    bool operator () (std::pair<std::string, Container> const& p)
    {
        return (p.first == _s);
    }

    std::string _s;
};

// ...

typedef std::vector<std::pair<std::string, Container> > my_vector;
my_vector v;

// ...

my_vector::iterator i = std::find_if(v.begin(), v.end(), comp("World"));
if (i != v.end())
{
    Container& c = i->second;
}

// ...

Here is a complete example:

#include <vector>
#include <utility>
#include <string>
#include <algorithm>

struct Container
{
    Container(int c) : _c(c) { }
    int _c;
};

struct comp
{
    comp(std::string const& s) : _s(s) { }

    bool operator () (std::pair<std::string, Container> const& p)
    {
        return (p.first == _s);
    }

    std::string _s;
};

#include <iostream>

int main()
{
    typedef std::vector<std::pair<std::string, Container> > my_vector;
    my_vector v;
    v.push_back(std::make_pair("Hello", Container(42)));
    v.push_back(std::make_pair("World", Container(1729)));
    my_vector::iterator i = std::find_if(v.begin(), v.end(), comp("World"));
    if (i != v.end())
    {
        Container& c = i->second;
        std::cout << c._c; // <== Prints 1729
    }
}

And here is a live example.

Solution 2

Using Boost.Range and Boost.Bind, you can do this:

struct predicate
{
    template<class Key, class Pair>
    bool operator()(const Key& k, const Pair& p) const
    {
        return p.first == k;
    }
};

// Your vector of pairs
std::vector<std::pair<std:string, Container> v = ...;
// The key you would like to search for
std::string key = ...;
Container& c = boost::find_if(v, boost::bind(predicate(), key, _1))->second;
Share:
26,780
Baz
Author by

Baz

Updated on July 27, 2022

Comments

  • Baz
    Baz almost 2 years

    I have a vector of pairs. The first in the pair is of type std::string and the second is of type Container.

    What convenient functionality exists in std or boost so that I can return a Container given the string value as key?

    UPDATE

    It has been commented that I could use a std::map instead, but I actually need to preserve the order of my items, in the order that I push them to the vector.

  • Steve Jessop
    Steve Jessop about 11 years
    Can't you just replace the copy with String_To_Data_Map string_to_data_map(string_data_pairs.begin(), string_data_pairs.end());?
  • qdii
    qdii about 11 years
    In that case, it would be possible to replace boost::bind with std::bind1st and get rid of boost this way.
  • Charles L Wilcox
    Charles L Wilcox about 11 years
    Yes... yes you can. I sometimes forget about the range-based constructors.
  • Erik
    Erik over 7 years
    it would appear that the link to the live example is broken