c - c 11排序自定义对象集合的多个属性

  显示原文与译文双语对照的内容

有一个自定义结构元素的集合:


struct MyStruct
{
 int id;
 std::string currencyCode;
 int month;
 int year;
 int amount;
};

这些数据将显示在允许按多个列排序的表中。

按一个属性对客户对象集合进行排序非常简单:


vector<MyStruct> values;

std::sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
{
 return lhs.key <rhs.key;
});

或者


struct MyStruct_x_Greater
{
 bool operator()( const MyStruct& lMyStruct, const MyStruct& rMyStruct ) const {
 return lMyStruct.x <rMyStruct.x;
 }
};

std::sort( values.begin(), values.end(), MyStruct_x_Greater() );

但是如何由多个属性逐个排序( 比如 sql ORDER BY column1 DESC, column2 ASC )?

时间:

只需更改比较器。假设你想要 ORDER BY 年,然后按月,然后按金额,然后:


std::sort( values.begin(), values.end(), [ ]( const MyStruct& lhs, const MyStruct& rhs )
{
 return std::tie(lhs.year, lhs.month, lhs.amount) <
 std::tie(rhs.year, rhs.month, rhs.amount);
});

std::tupleoperator< 做字典比较,所以不需要滚动你自己的( 并冒着错误的风险) 。 要对属性执行降序排序,只需交换 lhsrhs的属性。

按几个属性排序意味着定义重要性的顺序。 例如按年,月排序: 年份比月重要:


vector<MyStruct> values;
std::sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
{
 return lhs.year <rhs.year || ( lhs.year == rhs.year && lhs.month <rhs.month );
});

现有的答案忽略了在运行时选择排序顺序的需要。 我建议你给每个字段一个标识号,并添加一个函数来比较由标识指定的字段:


template <typename T>
int cmp(const T& lhs, const T& rhs)
{
 return lhs <rhs? -1 : lhs == rhs? 0 : 1;
}

struct MyStruct
{
 int id;//0
 std::string currencyCode;//1
 int month;//2
 int year;//3
 int amount;//4

 int cmp(int field_id, const MyStruct& rhs) const
 {
 switch (field_id)
 {
 case 0: return cmp(id, rhs.id);
 case 1: return cmp(currencyCode, rhs.currencyCode);
 case 2: return cmp(month, rhs.month);
 case 3: return cmp(year, rhs.year);
 case 4: return cmp(amount, rhs.amount);
 default: throw.. .cases out of sync with code...;
 }
 }
};

//update this as your column heading are clicked...
std::vector<int> sort_field_ids =.. .;

std::sort(begin(values), end(values),
 [&](const MyStruct& lhs, const MyStruct& rhs)
 {
 for (auto fid : sort_field_ids)
 {
 int cmp = lhs.cmp(fid, rhs);
 if (cmp) return cmp == -1;
 }
//fall back on something stable and unique
 return lhs.id <rhs.id;
 });

为了支持降序排序,请维护一个额外的标志( 例如。 std::vector<std::pair<int, bool>> sort_field_ids ),那么 return (cmp == -1) ^ descending; ( fid,descending 是从你的pair 中提取的,或者如果你愿意的话,将它们作为 .first/.second 来引用) 。

更好的是,找到一个在内部进行排序的带有体面网格/表格小部件的图形库。

仅当当前键的值相等时才使用下一个键:


[ ]( const MyStruct& lhs, const MyStruct& rhs )
{
 if(lhs.key1!= rhs.key1) 
 return lhs.key1 <rhs.key1;

 if(lhs.key2!= rhs.key2) 
 return lhs.key2 <rhs.key2;

. . . 

 return lhs.keyN <rhs.keyN;
}

在本例中,条目将被排序为 accroding key1,而不是 key2,等等。

...