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

StackOverflow https://stackoverflow.com/questions/279854

  •  07-07-2019
  •  | 
  •  

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>());
War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top