使用std::tie进行排序

using std::tie for sorting

本文关键字:排序 tie std 使用      更新时间:2023-10-16

我使用std::tie作为函子来对结构体列表进行排序。但我不明白为什么它不起作用。下面是我的代码:

#include <tuple>

class Point
{
 public:
    double x(void) const;
    double y(void) const;
    double z(void) const;
    double& x(void);
    double& y(void);
    double& z(void);
};
struct Xitem
{
    int ID;
    Point eP;
};

  class X_Struct_Sorter
  {
  public:
       X_Struct_Sorter(){}
      bool operator()(const Xitem& a, const Xitem& b)
       {
            return std::tie(a.eP.x(),a.eP.y(),a.eP.z(),a.ID)
                     <std::tie(b.eP.x(),b.eP.y(),b.eP.z(),b.ID);
       }
  };
 QList<Xitem> X_Structure;
 ///The function I use to sort X_Structure.  
 void sortX_Structure()
 {
       X_Struct_Sorter s();
       qSort(X_Structure.begin(),X_Structure.end(),s);
 }

我使用排序器对Xitem s的列表进行排序,我得到的只是eP.x()的排序。eP.y()未排序

问题:这里的问题是使用std::sort()qSort后Xitem列表的顺序不像我期望的那样。我这里想要的是字典顺序(x()->y()->z()->ID)。所以我想问题可能出在带有运算符的函子上

更新数据:这是应用这个函数后得到的数据。语法为:

    ID  | x() | y() | z()

输入为:

    0 | -38.8001 | 2.28723 | 0
   -1 | 1.26267 | 3.23 | 0
    1 | -38.1815 | 1.67529e-005 | 0
   -1 | -34.9763 | 0.334298 | 0
    2 | -34.2488 | 0.00119263 | 0
   -1 | 0.141234 | 0.839389 | 0
    3 | -38.1815 | 0.00364942 | 0
    -1 | 0.141234 | 0.839409 | 0
    4 | -38.1815 | 1.67529e-005 | 0
   -1 | -34.9763 | 0.334298 | 0
   5 | -38.1815 | 0.333395 | 0
  -1 | -38.1815 | 0.337506 | 0
  .....(sorry but the data is too long!)

输出为:

     20 | -38.8001 | 2.36565 | 0
     17 | -38.8001 | 0.333395 | 0
     21 | -38.8001 | 3.18365 | 0
     26 | -38.8001 | 0.3343 | 0
     23 | -38.8001 | 0.3343 | 0
     0 | -38.8001 | 2.28723 | 0
    22 | -38.8001 | 3.18364 | 0
    -1 | -38.8001 | 3.64414 | 0
    12 | -38.1815 | 0.334007 | 0 
You can see here in the first line of data. The `y()` of first Xitem is 2.36565 > 0.333395 of second one. So, I got a trouble here.

我的期望:

    17 | -38.8001 | 0.333395 | 0
     26 | -38.8001 | 0.3343 | 0
     23 | -38.8001 | 0.3343 | 0
     0 | -38.8001 | 2.28723 | 0
    20 | -38.8001 | 2.36565 | 0
     21 | -38.8001 | 3.18365 | 0
    22 | -38.8001 | 3.18364 | 0
    -1 | -38.8001 | 3.64414 | 0
    12 | -38.1815 | 0.334007 | 0 

就像你看到的,订单很糟糕。

std::tie要求左值Pointx()y()z()函数不返回引用,因此它们给出右值。一个简单的修复可能是为Point提供引用返回getter(例如double& x()),或者至少:

double ax = a.eP.x();
double ay = a.eP.y();
double az = a.eP.z();
double bx = b.eP.x();
double by = b.eP.y();
double bz = b.eP.z();
return std::tie(ax, ay, az, a.ID)
           < std::tie(bx, by, bz, b.ID);

你可以在这里阅读更多关于左值右值的信息。

jrok在评论中给出的另一个可能性是使用std::forward_as_tuple。然而,考虑到你的Point实现后,你的编辑似乎没有必要。

同样,正如Qt的文档中所指出的,你应该直接使用STL算法,Qt的函数将调用转发给它们:

从历史上看,Qt提供的函数直接等价于许多STL算法函数。从Qt 5.0开始,我们鼓励您直接使用STL中提供的实现;大多数Qt已被弃用(尽管它们仍然可用以保持旧代码的编译)。

您提供的代码在std::vectorstd::sort上正常工作,参见Ideone上的演示。