Jak sortować za pomocą lambda?


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

Chciałbym użyć funkcji lambda do sortowania niestandardowych klas zamiast wiązania metody instancji. Jednak powyższy kod powoduje błąd:

błąd C2564: „const char *”: konwersja stylu funkcji na typ wbudowany może przyjąć tylko jeden argument

Działa dobrze z boost::bind(&MyApp::myMethod, this, _1, _2).


Wektor jest strukturą zawierającą liczbę całkowitą i dwa łańcuchy. Właściwość tutaj byłaby liczbą całkowitą.
BTR,

4
Pokaż nam mały przykład do kompilacji .
GManNickG,

Odpowiedzi:


166

Rozumiem.

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

Założyłem, że dowie się, że operator> zwrócił wartość bool (zgodnie z dokumentacją). Ale najwyraźniej tak nie jest.


40
Więc co za bzdura operator>.
GManNickG,

2
To, co napisałeś do tej pory, nie ma sensu. Jeśli mProperty ma być wartością int a.mProperty>b.mProperty, z pewnością zwróci wartość bool.
sellibitze

8
Nie powinno tak być operator<, nie operator>?
Warpspace,

8
Tak, powinno być <, dla standardowej kolejności rosnącej. Zredagowałem odpowiedź, aby wyjaśnić, że była to sortowanie malejące, ale najwyraźniej moja edycja nie była pomocna i została wyczyszczona!
naleśnik

2
Właśnie wypróbowałem to w GCC 5.3.0 i -> boolczęść nie jest potrzebna.
David Grayson

23

Za dużo kodu możesz użyć w ten sposób:

#include<array>
#include<functional>

int main()
{
    std::array<int, 10> vec = { 1,2,3,4,5,6,7,8,9 };

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

    for (auto item : vec)
      std::cout << item << " ";

    return 0;
}

Zastąp „vec” swoją klasą i to wszystko.


Jak twoja odpowiedź różni się od BTR? Przy okazji. możesz użyć std :: begin (vec) i std :: end (vec), aby uczynić go bardziej c ++ 11.
Logman

Przepraszam, nie wiem, jak to przegapiłem. Moje oczy zatrzymują się na słupku Stephana. Mój błąd (modyfikuję post według twoich sugestii)
Adrian

5

Czy problem może dotyczyć wiersza „a.mProperty> b.mProperty”? Otrzymałem następujący kod do działania:

#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;
};

Wynik to:

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

Tak, coś dziwnego z konfiguracją, na której byłem. Kompilowanie na moim laptopie bez tego jest w porządku w wersji Team programu Visual Studio 2010. Co wskazało mi na to, że przełączyłem się z powrotem na bind, a błąd nie zniknie. Byłem na VC10 Express. Pluskwa?
BTR,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.