How to sort with a lambda?

225,048

Solution 1

Got it.

sort(mMyClassVector.begin(), mMyClassVector.end(), 
    [](const MyClass & a, const MyClass & b) -> bool
{ 
    return a.mProperty > b.mProperty; 
});

I assumed it'd figure out that the > operator returned a bool (per documentation). But apparently it is not so.

Solution 2

You can use it like this:

#include<array>
#include<functional>
using namespace std;
int main()
{
    array<int, 10> arr = { 1,2,3,4,5,6,7,8,9 };

    sort(begin(arr), 
         end(arr), 
         [](int a, int b) {return a > b; });

    for (auto item : arr)
      cout << item << " ";

    return 0;
}

Solution 3

Can the problem be with the "a.mProperty > b.mProperty" line? I've gotten the following code to work:

#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
#include <sstream>

struct Foo
{
    Foo() : _i(0) {};

    int _i;

    friend std::ostream& operator<<(std::ostream& os, const Foo& f)
    {
        os << f._i;
        return os;
    };
};

typedef std::vector<Foo> VectorT;

std::string toString(const VectorT& v)
{
    std::stringstream ss;
    std::copy(v.begin(), v.end(), std::ostream_iterator<Foo>(ss, ", "));
    return ss.str();
};

int main()
{

    VectorT v(10);
    std::for_each(v.begin(), v.end(),
            [](Foo& f)
            {
                f._i = rand() % 100;
            });

    std::cout << "before sort: " << toString(v) << "\n";

    sort(v.begin(), v.end(),
            [](const Foo& a, const Foo& b)
            {
                return a._i > b._i;
            });

    std::cout << "after sort:  " << toString(v) << "\n";
    return 1;
};

The output is:

before sort: 83, 86, 77, 15, 93, 35, 86, 92, 49, 21,
after sort:  93, 92, 86, 86, 83, 77, 49, 35, 21, 15,
Share:
225,048

Related videos on Youtube

BTR
Author by

BTR

Updated on March 16, 2022

Comments

  • BTR
    BTR about 2 years
    sort(mMyClassVector.begin(), mMyClassVector.end(), 
        [](const MyClass & a, const MyClass & b)
    { 
        return a.mProperty > b.mProperty; 
    });
    

    I'd like to use a lambda function to sort custom classes in place of binding an instance method. However, the code above yields the error:

    error C2564: 'const char *' : a function-style conversion to a built-in type can only take one argument

    It works fine with boost::bind(&MyApp::myMethod, this, _1, _2).

    • BTR
      BTR about 13 years
      The vector is of a struct which contains an integer and two strings. The property here would be an integer.
    • GManNickG
      GManNickG about 13 years
      Show us a small compilable example.
  • sellibitze
    sellibitze about 13 years
    What you have written so far makes little sense. If mProperty is supposed to be an int a.mProperty>b.mProperty will definitely yield a bool.
  • BTR
    BTR about 13 years
    Then you understand my confusion. I think it might be something weird with my VC10 Express (no service pack). I moved the project onto a machine with Visual Studio 2010 Team and it worked without the "-> bool".
  • BTR
    BTR about 13 years
    Yeah, something screwy with the setup I was on. Compiling on my laptop without it just fine on the Team edition of Visual Studio 2010. What clued me in what that I'd switched back to bind and the error wouldn't go away. I was on VC10 Express. Bug?
  • BTR
    BTR about 13 years
    And yes, the property is int32_t.
  • BTR
    BTR about 13 years
    Hey GMan, I noticed that you have found Lambda bugs with VS per your site: gmannickg.com/?p=38. Possibly related issue in the Express edition?
  • Warpspace
    Warpspace over 10 years
    Shouldn't it be operator<, not operator>?
  • pancake
    pancake almost 10 years
    Yes it should be <, for standard ascending order. I edited the answer to make it clear it was a descending sort but apparently my edit was unhelpful and got wiped!
  • David Grayson
    David Grayson almost 8 years
    I just tried this in GCC 5.3.0 and the -> bool part is not needed.
  • Conrad Jones
    Conrad Jones about 5 years
    it was highly likely explicitly specifying the -> boot return type was required due to a VC bug.
  • Admin
    Admin over 3 years
    make it longer, thats why op wants to use a lambda