ChatGPT解决这个技术问题 Extra ChatGPT

如何根据对的第二个元素对对的向量进行排序?

如果我有一对向量:

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

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

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

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

std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());
这是一个例子:<br> std::sort in a vector of pairs
c++ 没有 lamdas,所以你不能完全按照你的意愿去做,你需要创建一个单独的函数/仿函数。这可以是单行的,所以它真的不应该是什么大不了的。
C++ 现在有 lambdas 了!哇!

E
Evan Teran

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

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


请记住,这与 pair<T1,T2> 中的 operator< 不同。默认比较器使用 both 第一个和第二个元素(如果第一个元素相等)。这里只使用了第二个。
@Googol:这正是 OP 所要求的......他说:"is there and easy way to sort the list in increasing order based on the second element of the pair?"
@evan-teran,是的,我知道。我只是指出如果两个秒元素相等,那么结果可能会令人困惑(例如,如果用于排序)。默认比较器不会遇到此问题,因为它使用第二个元素进行平局。我遇到了这个问题,寻找一个比较器,它使用第二个元素作为比较的主要信息,但我还需要它使用第一个元素来打破平局,所以我想避免其他人错过这一点(正如我在事实上,确实)。
J
Johannes Schaub - litb

您可以像这样使用提升:

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

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


+1 使用 Boost。顺便说一句,使用现代编译器,您可能已经将 boost 替换为 std::tr1 ,因为这将很快成为标准。
不幸的是,我对 gcc trunk 的 c++1x std::bind 进行了同样的尝试,但它失败了,因为它没有用于绑定的 op<。但是不知道 c++1x 对此有何评论。可能它会告诉您为此使用 lambda :)
我想提升不是标准的,但它已经足够接近了。 :-)
在此处发布了对此答案的后续问题:stackoverflow.com/q/4184917/220636
E
Ezio

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

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

简单而“中肯”。不需要提升或特定的 C++ 版本。 +1
这应该被标记为最佳解决方案。不需要 c++14 来实现它。
你能解释一下这个比较是如何工作的吗?我们是否一次将两个元素传递给 myComparision 那么它如何排序?另外, a.second
myComparison 函数由 sort 函数调用,其中 sort 函数发送两个值并期望 True 或 False 以便它确定哪个应该放在第一位,哪个元素应该放在第二位,这就是比较函数如何帮助开发者自己定义大于和小于的定义
A
Andreas Spindler

使用 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)后返回表达式的类型;否则无效。

要显式指定返回类型,请使用 []() -> 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; } );

为什么是if (lhs.second == 0)
没有特别的意义; lhs.second < rhs.second 可能返回 truefalse,编译器可以清楚地推导出 bool。只是想演示 []() -> Type { } 案例。
至少对于 clang,这种隐式推导可能无法正常工作,我必须添加 ->bool 作为 lambda 返回类型才能使其正常工作。
L
Leon Timmermans

对于可重用的东西:

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

G
Greg Rogers

您必须依赖非标准的 select2nd


u
underscore_d

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