按多个值对矢量进行排序

Sort vector by multiple values

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

我必须对向量进行排序。向量包含指向类"student"对象的指针。

评级指标如下:

  1. 最佳财务交易
  2. 如果最终交易相同,尝试次数就会减少
  3. 如果尝试相同,则id更少
  4. 尝试次数为0次的学生比尝试次数为2次的学生差,最终成绩为5,按较少id对尝试次数为零的学生进行排序

学生看起来像这样:

private:
std::string name_;
int id_;
int attempts_;  //max 2, if 0, exam not taken
int grade1_;
int grade2_;
int finalGrade_;  // grade 5 for failed exam but still better than 0 attempts in rating

我的问题是我不知道如何处理尝试。因为最好的尝试次数是1,并且它比2次尝试好。但是2次尝试在评级上优于0。

我希望你能理解我的问题并能帮助我

STL中有一个可用的函数,称为std::sort,它可以采用比较器函数(函数指针或函数对象)。

comparator函数必须返回一个布尔值,说明第一个元素是否应该严格出现在第二个元素之前。

以下是我为比较器设计的:

struct compare_student {
inline bool 
operator() (Student *left, Student *right) const
{
if(left->attempts_ == 0 && right->attempts_ == 0)
return left->id_ < right->id_;
else if(left->attempts_ == 0)
return false;
else if(right->attempts_ == 0)
return true;
return 
left->finalGrade_ <  right->finalGrade_ ||    // Compare final grade
left->finalGrade_ == right->finalGrade_ && (  // If final grade same:
left->attempts_ <  right->attempts_ ||    // Compare attempts
left->attempts_ == right->attempts_ && (  // If attempts same:
left->id_ < right->id_                // Compare id's
)
);
}
};

显然,您所有的字段都是私有的,因此您需要使用它们的访问器方法,而不仅仅是直接访问它们,但以下是使用方法:

vector<Student *> students {...};
std::sort(students.begin(), students.end(), compare_student{});

std::sort是不稳定的,这意味着如果两个元素被认为是相等的,那么它们不一定会保持它们的相对顺序,这对你来说可能很重要。如果是,那么也有一个名为std::stable_sort的函数,确实有这样的保证,并且以完全相同的方式使用:

std::stable_sort(students.begin(), students.end(), compare_students{});

编辑关于实施的说明

  • compare_students是一个只有一个公共成员的类,所以与其这样做:

    class compare_student {
    public:
    ...
    };
    

    我把它缩短为:

    struct compare_student {
    ...
    };
    

    (两者在C++中是等价的,结构只是一个具有默认公共访问权限的类。)

  • 那么inline bool operator()是什么意思呢。

    • inline向编译器提示,此函数可以内联,也就是说,用代码本身替换调用
    • bool是函数的返回类型
    • operator()是函数的名称,它是一个特殊情况下的函数,当你像函数一样对待对象时会被调用:

      Student *a, *b;
      compare_student comparator {};
      comparator(a, b); // calls comparator::operator()(a, b)
      

听起来比较函数的第一行应该是

if (left.attempts_ == 0)

从那里,检查是否也有right.attempts_ == 0。如果是,请检查ID。

如果没有,那么右边有分数,左边没有,右边更好。

继续执行其余规则。最终,您可以使用类似if (left.attempts_ < right.attempts_)的规则,但只有在处理了0次尝试之后。