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



代码将根据第一个元素和第二个元素对std::对进行排序(如果第一个元素相等(。

有人能告诉我如何使用元组根据第三个元素进行排序吗?如果第一个和第二个恰好相等?

我们想知道的是如何使用谓词根据第一个、第二个(如果第一个相等(和第三个(如果第一个和第二个相等(进行排序?

例如,如果我有:

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

我们想知道的是如何使用谓词根据第一个、第二个(如果第一个和第二个相等(和第三个(如果第二个和第一个相等(进行排序?

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

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

注意,我已经在std::get<2>:中的ab之间交换了位置

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

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

如果你想在没有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);
}
};

最新更新