Come ordinare con una lambda?


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

Vorrei usare una funzione lambda per ordinare le classi personalizzate al posto di un metodo di istanza associato. Tuttavia, il codice sopra genera l'errore:

errore C2564: 'const char *': una conversione di tipo funzione in un tipo incorporato può accettare solo un argomento

Funziona bene con boost::bind(&MyApp::myMethod, this, _1, _2).


Il vettore è di una struttura che contiene un numero intero e due stringhe. La proprietà qui sarebbe un numero intero.
BTR,

4
Mostraci un piccolo esempio compilabile .
GManNickG,

Risposte:


158

Fatto.

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

Ho pensato che avrebbe scoperto che l'operatore> ha restituito un bool (secondo la documentazione). Ma a quanto pare non è così.


39
Che schifo operator>, quindi.
GManNickG,

2
Ciò che hai scritto finora ha poco senso. Se si suppone che mProperty sia un int a.mProperty>b.mPropertygenererà sicuramente un bool.
sellibitze,

1
Allora capisci la mia confusione. Penso che potrebbe essere qualcosa di strano con il mio VC10 Express (nessun service pack). Ho spostato il progetto su una macchina con Visual Studio 2010 Team e ha funzionato senza "-> bool".
BTR,

8
Non dovrebbe essere operator<, no operator>?
Warpspace,

8
Sì, dovrebbe essere <, per ordine crescente standard. Ho modificato la risposta per chiarire che si trattava di un ordinamento discendente, ma a quanto pare la mia modifica non è stata utile e è stata cancellata!
pancake

19

Per molto codice, puoi usarlo in questo modo:

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

Sostituisci "vec" con la tua classe e il gioco è fatto.


In che modo la tua risposta è diversa da BTR? Btw. puoi usare std :: begin (vec) e std :: end (vec) per renderlo più c ++ 11.
Logman,

Scusa, non so come mi sia perso. I miei occhi si fermano al posto di Stephan. Mio cattivo (modifico il post dopo i tuoi suggerimenti)
Adrian

5

Il problema può riguardare la riga "a.mProperty> b.mProperty"? Ho ottenuto il seguente codice per funzionare:

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

L'output è:

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

Sì, qualcosa di strano con la configurazione in cui mi trovavo. Compilare sul mio laptop senza farlo bene sull'edizione Team di Visual Studio 2010. Ciò che mi ha indotto in ciò che ero tornato a legare e l'errore non sarebbe scomparso. Ero su VC10 Express. Bug?
BTR,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.