143

如果我有一对向量:

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

有没有简单的方法根据对的第二个元素按升序对列表进行排序?

我知道我可以编写一个小函数对象来完成这项工作,但是有没有办法使用STL的现有部分并std::less直接完成这项工作?

编辑:我知道我可以编写一个单独的函数或类来传递给第三个参数进行排序。问题是我是否可以用标准的东西来构建它。我真的会看起来像:

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

7 回答 7

236

编辑:使用 c++14,最好的解决方案很容易编写,这要归功于现在可以具有 type 参数的 lambdas auto这是我目前最喜欢的解决方案

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

原始答案

只需使用自定义比较器(它是可选的第三个参数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());

如果您使用的是 C++11 编译器,则可以使用 lambdas 编写相同的代码:

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

编辑:针对您对问题的编辑,这里有一些想法......如果您真的想有创意并且能够大量重用这个概念,只需制作一个模板:

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

于 2008-11-11T02:56:21.957 回答
71

您可以像这样使用提升:

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

我不知道一个标准的方法来做到这一点同样简短,但你可以抓住boost::bind它全部由标题组成。

于 2008-11-11T06:02:04.313 回答
41

它非常简单,您可以使用算法中的排序功能并添加您自己的比较功能

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

现在您必须根据第二个选择进行比较,因此将“myComparison”声明为

bool myComparison(const pair<int,int> &a,const pair<int,int> &b)
{
       return a.second<b.second;
}
于 2015-11-11T11:20:26.710 回答
30

使用 C++0x,我们可以使用 lambda 函数:

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是隐式推导的。

Lambda 返回类型

当 lambda 函数只有一条语句并且这是一个返回语句时,编译器可以推断返回类型。从 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; } );
于 2011-11-03T21:42:56.200 回答
5

对于可重用的东西:

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>());
于 2008-11-11T11:33:34.783 回答
1

您必须依赖非标准的select2nd

于 2008-11-11T02:48:19.943 回答
-1

尝试交换对的元素,以便您可以std::sort()正常使用。

于 2017-01-12T07:58:48.250 回答