web-dev-qa-db-ja.com

ペアの2番目の要素に基づいてペアのベクトルをソートするにはどうすればよいですか?

ペアのベクトルがある場合:

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

ペアの2番目の要素に基づいてリストを昇順で並べ替える簡単な方法はありますか?

私は仕事をする小さな関数オブジェクトを書くことができることを知っていますが、STLstd::lessの既存の部分を使用して直接仕事をする方法はありますか?

編集:私は、ソートするために3番目の引数に渡す別の関数またはクラスを書くことができることを理解しています。問題は、標準のものから構築できるかどうかです。私は本当に次のように見える何かをしたい:

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

EDIT:c ++ 14を使用すると、タイプautoのパラメーターを持つことができるラムダのおかげで、最適なソリューションは非常に簡単に記述できます。 これは私の現在のお気に入りのソリューションです

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

カスタムコンパレータを使用するだけです(std::sortのオプションの3番目の引数です)

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());

C++ 11コンパイラを使用している場合、ラムダを使用して同じことを記述できます。

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

EDIT:質問への編集に応じて、ここにいくつかの考えがあります... 本当に創造的であり、この概念を何度も再利用したい場合テンプレートを作成します。

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

それからこれもできます:

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

あるいは

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

正直に言って、これは少しやり過ぎです。3行の関数を書いて、それで完了です:-P

188
Evan Teran

次のようなブーストを使用できます。

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

これを同様に短く簡潔に行う標準的な方法はわかりませんが、boost::bindを取得できます。すべてヘッダーで構成されています。

C++ 0xでは、ラムダ関数を使用できます。

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

この例では、戻り型boolが暗黙的に推論されます。

ラムダ戻り型

ラムダ関数に単一のステートメントがあり、これが戻りステートメントである場合、コンパイラーは戻りタイプを推測できます。 C++ 11から、§5.1.2/ 4:

...

  • 複合ステートメントが{ return expression ; }形式の場合、左辺値から右辺値への変換(4.1)、配列からポインターへの変換(4.2)、および関数からポインターへの変換(4.3 );
  • それ以外の場合は、void

戻り値の型を明示的に指定するには、次のように[]() -> Type { }の形式を使用します。

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

アルゴリズムからsort関数を使用し、独自の比較関数を追加するのは非常に簡単です

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

次に、2番目の選択に基づいて比較を行う必要があるため、「myComparison」を次のように宣言します。

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

再利用可能なものの場合:

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

次のように使用できます

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

または

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

非標準に依存する必要があります select2nd

1
Greg Rogers