C ++如何根据第一个,然后第二个,然后第三个对元组进行排序

时间:2020-09-15 19:44:29

标签: c++

代码将基于第一个元素然后按第二个std :: pair排序(如果第一个元素相等)。

有人可以告诉我如何使用元组基于第三个元素进行排序吗?如果第一和第二碰巧相等?

想知道的是如何使用谓词对第一个,第二个(如果第一个相等),然后第三个(如果第一个和第二个相等)进行排序呢?

例如,如果我有:

(3,2,3)
(1,1,0)
(1,1,1)
(2,2,2)

它将打印:

(1,1,0)
(1,1,1)
(2,2,2)
(3,2,3)

代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>

typedef std::pair<double, double> my_pair;

struct sort_pred
{
    bool operator ()( const my_pair &left, const my_pair &right ) const
    {
        return ( left.first < right.first ) || 
               ( !( right.first < left.first ) && ( right.second > left.second ) );
    }
};

int main()
{
    std::vector<my_pair> data;

    data.push_back( my_pair( 3, 2 ) );
    data.push_back( my_pair( 1, 2 ) );
    data.push_back( my_pair( 1, 1 ) );
    data.push_back( my_pair( 2, 2 ) );

    std::stable_sort( data.begin(), data.end(), sort_pred() );

    for ( const auto &p : data ) std::cout << p.first << ' ' << p.second << std::endl;
}  

1 个答案:

答案 0 :(得分:2)

想知道的是如何使用谓词对第一个,第二个(如果第一个相等),然后第三个(如果第一个和第二个相等)进行排序呢?

std::tuple已经有一个operator<可以执行上述操作,但是要手动执行,人们最常使用的是std::tie,它本身会创建一个提供的参数的元组。具有三个字段(f1-f3)的类的比较函子可以是:

[](auto& a, auto& b) { return std::tie(a.f1, a.f2, a.f3) < std::tie(b.f1, b.f2, b.f3); }

为了显示一些不同的内容,假设您希望前两个字段的排序顺序为升序,而最后一个字段的排序顺序为降序。

请注意,我在a中的bstd::get<2>之间交换了位置:

auto comp = [](auto& a, auto& b) {
    return
        std::tie(std::get<0>(a), std::get<1>(a), std::get<2>(b))
        <
        std::tie(std::get<0>(b), std::get<1>(b), std::get<2>(a));
};

std::sort(data.begin(), data.end(), comp);

这会给您以下命令:

1,1,1
1,1,0
2,2,2
3,2,3

ab换回std::get<2>,您将获得与原始元组已经内置的顺序相同的顺序。

如果您想在没有std::tie的帮助下进行此操作,可以这样做:

struct sort_pred {
    bool operator ()(const my_tuple& left, const my_tuple& right) const {
        if(std::get<0>(left) != std::get<0>(right)) 
            return std::get<0>(left) < std::get<0>(right);

        if(std::get<1>(left) != std::get<1>(right))
            return std::get<1>(left) < std::get<1>(right);

        return std::get<2>(left) < std::get<2>(right);
    }
};

或者如果您希望使用很多三元运算符,也可以这样做。我觉得它读起来有点难,但是我想这是一个品味问题:

struct sort_pred {
    bool operator ()(const my_tuple& left, const my_tuple& right) const {
        return 
            std::get<0>(left) != std::get<0>(right) ? std::get<0>(left) < std::get<0>(right) :
            std::get<1>(left) != std::get<1>(right) ? std::get<1>(left) < std::get<1>(right) :
            std::get<2>(left) < std::get<2>(right);
    }
};