Reputation: 255
i have to sort a vector. The vector contains pointers to objects of class "student".
the rating metric looks like this:
student looks like this:
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
my problem is that i dont know how to handle attempts. because best number of attempts is 1 and its better than 2 attempts. but 2 attempts are better than 0 in the rating.
i hope you understand my problem and can help me. thx :)
Upvotes: 3
Views: 3514
Reputation: 3716
There is a function available in the STL, called std::sort
Which can take a comparator function, (either a function pointer, or a function object).
The comparator function has to return a boolean that says whether the first element should appear strictly before the second element.
Here's what I came up with for the 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
)
);
}
};
Obviously all your fields are private, so you will need to use their accessor methods rather than just accessing them directly, but here's how you use it:
vector<Student *> students {...};
std::sort(students.begin(), students.end(), compare_student{});
std::sort
is not stable, this means if two elements are considered equal, then it is not necessarily the case that they will keep their relative order, which may be important to you. If it is, then there is also a function called std::stable_sort
which does have such a guarantee, and is used in exactly the same way:
std::stable_sort(students.begin(), students.end(), compare_students{});
EDIT Notes on the implementation
compare_students
is a class that has only one, public member, so rather than do this:
class compare_student {
public:
...
};
I shortened it to this:
struct compare_student {
...
};
(the two are equivalent in C++, a struct is just a class with default public access.)
Then as to what inline bool operator()
means.
inline
is a hint to the compiler that this function can be inlined, that is to say, replace the call with the code itself.bool
is the return type of the function.operator()
is the name of the function, It is a special-case function that gets called when you treat an object like a function:
Student *a, *b;
compare_student comparator {};
comparator(a, b); // calls comparator::operator()(a, b)
Upvotes: 8
Reputation: 283684
Sounds like the first line of your comparison function should be
if (left.attempts_ == 0)
From there, check whether right.attempts_ == 0
as well. If yes, check the IDs.
If no, then right has a grade and left doesn't, right is better.
Continue on with the rest of the rules. Eventually you can use rules like if (left.attempts_ < right.attempts_)
but only after you've dealt with 0 attempts.
Upvotes: 1