Wie sortiere ich einen Vektor von Paaren basierend auf dem zweiten Element des Paares?
Frage
Wenn ich einen Vektor von Paaren:
std::vector<std::pair<int, int> > vec;
Sie haben und einfache Möglichkeit, die Liste in aufsteigender Reihenfolge zu sortieren auf dem zweiten Element des Paares?
Ich weiß, ich kann ein wenig Funktion Objekt schreiben, die die Arbeit tun, aber ist es eine Möglichkeit, bestehende Teile des verwenden STL und std::less
die Arbeit direkt zu tun?
EDIT: Ich verstehe, dass ich eine separate Funktion oder Klasse schreiben kann auf das dritte Argument übergeben zu sortieren. Die Frage ist, ob ich es aus Standard-Sachen zu bauen. Ich würde wirklich etwas, das wie folgt aussieht:
std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());
Lösung
Bearbeiten : mit C ++ 14, die beste Lösung ist sehr einfach zu bedienen dank lambdas zu schreiben, die jetzt Parameter vom Typ auto
haben. Das ist meine aktuelle Lieblings Lösung
std::sort(v.begin(), v.end(), [](auto &left, auto &right) {
return left.second < right.second;
});
Verwenden Sie einfach einen benutzerdefinierten Komparator (es ist ein optionales drittes Argument 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 die gleiche mit Lambda-Ausdrücke schreiben:
std::sort(v.begin(), v.end(), [](const std::pair<int,int> &left, const std::pair<int,int> &right) {
return left.second < right.second;
});
Bearbeiten : als Antwort auf Ihre Änderungen auf Ihre Frage, hier einige Gedanken ... wenn Sie auf wirklich will kreativ sein und in der Lage, dieses Konzept wieder zu verwenden viel, nur eine Vorlage machen:
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 können Sie dies tun, auch:
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> >());
Obwohl ehrlich zu sein, das ist alles ein bisschen übertrieben, schreiben Sie einfach den 3-Line-Funktion und mit ihm getan werden :-P
Andere Tipps
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 weiß nicht, einen Standard-Weg, dies ebenso kurz und prägnant zu tun, aber Sie können boost::bind
packen es alles von Headern aus.
Mit C ++ 0x wir Lambda-Funktionen verwenden können:
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 der Rückgabetyp bool
implizit abgeleitet wird.
Lambda Rückgabetypen
Wenn eine Lambda-Funktion eine einzige Anweisung hat, und das ist eine Rückkehr-Anweisung kann der Compiler den Rückgabetyp abzuleiten. Von C ++ 11, §5.1.2 / 4:
...
- Wenn die Verbindung-Anweisung hat die Form
{ return expression ; }
den Typen der zurück Expression nach lvalue-zu-R-Wert-Umwandlung (4.1), array-zu-Zeiger-Umwandlung (4.2), und die Funktion-zu-Zeiger-Umwandlung (4.3) ;- andernfalls
void
.
Um explizit angeben, der Rückgabetyp die Form []() -> Type { }
verwenden, 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; } );
Es ist ziemlich einfach verwenden Sie die Sortierfunktion von Algorithmus und fügen Sie Ihre eigene Vergleichsfunktion
vector< pair<int,int > > v;
sort(v.begin(),v.end(),myComparison);
Nun müssen Sie den Vergleich machen auf der Grundlage der zweiten Auswahl so erklären Sie "myComparison" als
bool myComparison(const pair<int,int> &a,const pair<int,int> &b)
{
return a.second<b.second;
}
Für etwas wiederverwendbar:
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>());
Sie müßten auf einem Nicht-Standard vertrauen select2nd
Versuchen Sie, die Elemente der Paare tauschen, so dass Sie std::sort()
wie gewohnt verwenden können.