it-swarm.com.de

Wie sortiere ich einen Vektor von Paaren basierend auf dem zweiten Element des Paares?

Wenn ich einen Vektor von Paaren habe:

std::vector<std::pair<int, int> > vec;

Gibt es eine einfache Möglichkeit, die Liste in aufsteigender Reihenfolge nach dem zweiten Element des Paares zu sortieren?

Ich weiß, dass ich ein kleines Funktionsobjekt schreiben kann, das die Arbeit erledigt, aber es gibt eine Möglichkeit, vorhandene Teile des STL und std::less, um die Arbeit direkt zu erledigen?

EDIT: Ich verstehe, dass ich eine separate Funktion oder Klasse schreiben kann, um an das dritte Argument zum Sortieren zu übergeben. Die Frage ist, ob ich es aus Standardmaterialien bauen kann oder nicht. Ich hätte wirklich etwas, das so aussieht:

std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());
120
David Norman

EDIT : Mit c ++ 14 ist die beste Lösung sehr einfach zu schreiben, dank Lambdas, die jetzt Parameter vom Typ auto haben können. Dies ist meine derzeitige Lieblingslösung

std::sort(v.begin(), v.end(), [](auto &left, auto &right) {
    return left.second < right.second;
});

Verwenden Sie einfach einen benutzerdefinierten Komparator (optionales drittes Argument für std::sort)

struct sort_pred {
    bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
        return left.second < right.second;
    }
};

std::sort(v.begin(), v.end(), sort_pred());

Wenn Sie einen C++ 11-Compiler verwenden, können Sie dasselbe mit lambdas schreiben:

std::sort(v.begin(), v.end(), [](const std::pair<int,int> &left, const std::pair<int,int> &right) {
    return left.second < right.second;
});

EDIT : Als Antwort auf Ihre Änderungen an Ihrer Frage, hier einige Gedanken ... wenn Sie wirklich kreativ sein und in der Lage sein möchten Um dieses Konzept häufig wiederzuverwenden, erstellen Sie einfach eine Vorlage:

template <class T1, class T2, class Pred = std::less<T2> >
struct sort_pair_second {
    bool operator()(const std::pair<T1,T2>&left, const std::pair<T1,T2>&right) {
        Pred p;
        return p(left.second, right.second);
    }
};

dann kannst du das auch machen:

std::sort(v.begin(), v.end(), sort_pair_second<int, int>());

oder auch

std::sort(v.begin(), v.end(), sort_pair_second<int, int, std::greater<int> >());

Um ehrlich zu sein, ist das alles ein bisschen übertrieben. Schreiben Sie einfach die 3-Zeilen-Funktion und fertig :-P

188
Evan Teran

Sie können Boost wie folgt verwenden:

std::sort(a.begin(), a.end(), 
          boost::bind(&std::pair<int, int>::second, _1) <
          boost::bind(&std::pair<int, int>::second, _2));

Ich kenne keine Standardmethode, um dies ebenso kurz und prägnant zu machen, aber Sie können boost::bind Alles besteht aus Überschriften.

Mit C++ 0x können wir Lambda-Funktionen verwenden:

using namespace std;
vector<pair<int, int>> v;
        .
        .
sort(v.begin(), v.end(),
     [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
             return lhs.second < rhs.second; } );

In diesem Beispiel wird implizit der Rückgabetyp bool abgeleitet.

Lambda-Rückgabetypen

Wenn eine Lambda-Funktion eine einzelne Anweisung hat und dies eine return-Anweisung ist, kann der Compiler den return-Typ ableiten. In C++ 11, §5.1.2/4:

...

  • Wenn die zusammengesetzte Anweisung die Form { return expression ; } Hat, wird der Typ des zurückgegebenen Ausdrucks nach der Umwandlung von lWert in rWert (4.1), der Umwandlung von Array in Zeiger (4.2) und der Umwandlung von Funktion in Zeiger ( 4.3);
  • ansonsten void.

Um den Rückgabetyp explizit anzugeben, verwenden Sie das Formular []() -> Type { }, wie in:

sort(v.begin(), v.end(),
     [](const pair<int, int>& lhs, const pair<int, int>& rhs) -> bool {
             if (lhs.second == 0)
                 return true;
             return lhs.second < rhs.second; } );
30

Es ist ziemlich einfach, wenn Sie die Sortierfunktion des Algorithmus verwenden und Ihre eigene Vergleichsfunktion hinzufügen

vector< pair<int,int > > v;
sort(v.begin(),v.end(),myComparison);

Jetzt müssen Sie den Vergleich anhand der zweiten Auswahl durchführen und "myComparison" als deklarieren

bool myComparison(const pair<int,int> &a,const pair<int,int> &b)
{
       return a.second<b.second;
}
29
Ezio

Für etwas wiederverwendbares:

template<template <typename> class P = std::less >
struct compare_pair_second {
    template<class T1, class T2> bool operator()(const std::pair<T1, T2>& left, const std::pair<T1, T2>& right) {
        return P<T2>()(left.second, right.second);
    }
};

Sie können es als verwenden

std::sort(foo.begin(), foo.end(), compare_pair_second<>());

oder

std::sort(foo.begin(), foo.end(), compare_pair_second<std::less>());
5
Leon Timmermans

Sie müssten sich auf ein nicht standardmäßiges select2nd verlassen

1
Greg Rogers