16

I want to find the std::lower_bound of the a std::vector of std::pair's according to the second element with lambda.

std::vector < std::pair <int, double> > vec;
vec.resize(5);

auto it = std::lower_bound(vec.begin(), vec.end(), lambda);
// what is that lambda here?
Shibli
  • 5,879
  • 13
  • 62
  • 126

2 Answers2

27

You're missing an argument here, std::lower_bound takes a begin and end iterator, a value (this is what you missed) and finally can take a lambda.

#include <algorithm>
#include <vector>

int main()
{
    typedef std::pair<int, double> myPair; // typedef to shorten the type name
    std::vector <myPair> vec(5);

    myPair low_val; // reference value (set this up as you want)
    auto it = std::lower_bound(vec.begin(), vec.end(), low_val, 
        [](myPair lhs, myPair rhs) -> bool { return lhs.second < rhs.second; });
}

Reference page for lower_bound is here.

Borgleader
  • 15,826
  • 5
  • 46
  • 62
  • good but how I can print the value `it` pointing to? `std::cout << *it << std::endl` or `std::cout << *(it.second) << std::endl` does not work. – Shibli Jul 17 '13 at 23:11
  • Try: (*it).second, also make sure your vector is sorted. – Borgleader Jul 17 '13 at 23:13
  • Oh thanks. The last thing is that what are those `lhs` and `rhs` and why I take the smaller one? – Shibli Jul 17 '13 at 23:19
  • lhs and rhs are acronyms for left hand side and right hand side. And you take the smaller because you want the lower bound. – Borgleader Jul 17 '13 at 23:21
  • Then should not it be smaller and equal to instead of just taking the smaller one according to the definition of the lower_bound? Also I just put upper_bound instead of lower_bound, then it gave the correct answer even though I did not change the sign. – Shibli Jul 17 '13 at 23:25
  • 1
    Look [here](http://en.cppreference.com/w/cpp/algorithm/lower_bound), the comp function should return true if the first argument (lhs) is smaller than the second (rhs). And the comp function for upper bound is the same (see [here](http://en.cppreference.com/w/cpp/algorithm/upper_bound)) it how it was standardized. – Borgleader Jul 17 '13 at 23:29
15

The purpose of lower_bound is to find the position where an element would go. So you have to specify that element. If you only want to sort by the second partner, then you just need to specify a value for that:

std::vector<std::pair<int, double>> vec = /* populate */ ; // must be sorted!

double target = 1.3;

auto it = std::lower_bound(vec.begin(), vec.end(), target,
          [](std::pair<int, double> const & x, double d)
          { return x.second < d; });

Note that the vector must be sorted according to the same predicate, though, so you might want to store the predicates more permanently:

auto lb_cmp =   [](std::pair<int, double> const & x, double d) -> bool
                { return x.second < d; };

auto sort_cmp = [](std::pair<int, double> const & x,
                   std::pair<int, double> const & y) -> bool
                { return x.second < y.second; };

std::sort(vec.begin(), vec.end(), sort_cmp);

auto it = std::lower_bound(vec.begin(), vec.end(), target, lb_cmp);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Are you sure this code compiles? It seems to me that `std::sort()` would require a lambda of the `[](std::pair, std::pair){}` variety. – Adrian Mar 07 '15 at 17:22