1

I am trying to sort students name and their marks. I want to sort mark first then sort string of student names with same marks.

Here is my code so far:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    struct student
    {
        int mark;
        string name;
       
    };

    vector <student> s = {
    {30, "Mark"},
    {14, "Mitch"},
    {23, "Hen"},
    {30, "Abo"}
    };

    sort(s.begin(), s.end(), [](const student& a, const student& b) { return (a.mark < b.mark); });

    for (const auto& x : s)
        cout << x.mark << ", " << x.name << endl;
}

This code outputs as expected (sorts marks):

14, Mitch
23, Hen
30, Mark
30, Abo

However, I also want it to sort name of students with same grades, i.e. Mark and Abo have same marks of 30, therefore Abo should come before Mark (due to the alphabetical order of their names).

Expected output:

14, Mitch
23, Hen
30, Abo
30, Mark
1
  • Hint: that comparator lambda is going to get a bit more.. involved. Commented Apr 18, 2021 at 13:07

3 Answers 3

5

You could use std::tie:

std::sort(s.begin(), s.end(), [](const student& a, const student& b) 
         { return std::tie(a.mark, a.name) < std::tie(b.mark, b.name); });

Using std::tie makes it a little easier to write comparators that "cascade" from one entry to the next when there is (no pun intended) a "tie" in one of the entries.

Sign up to request clarification or add additional context in comments.

Comments

1

You should use a comparision function that matches your specification.

sort(s.begin(), s.end(),
    [](const student& a, const student& b) {
        return
            a.mark < b.mark // a < b if a.mark is less than b.mark
            ||
            (a.mark == b.mark && // when a.mark equals to b.mark
             a.name < b.name);   // compare their name
    }
);

3 Comments

hey @MikeCAT thank you for the answer, I just split the class into .h file and i get this error Error C2664 'bool main: <lambda_f3246fe66175cccfd1eb8cc0144b5949> ::operator ()(const Student &,const Student &) const': cannot convert argument 1 from 'Student *' to 'const Student &' Any idea on why i am getting this?
It looks like bcause you are passing Student* where Student is expected.
Hey @MikeCAT thank you for quick reply, the error went away but another error appeared, Error C2440 'initializing': cannot convert from 'student' to 'student', any idea why? thank you for your time. Appreciate it
1

You can use the ternary operator to check if the marks are equal and, if so, compare the names; otherwise just compare the marks:

sort(s.begin(), s.end(), [](const student& a, const student& b) {
    return (a.mark == b.mark) ? (a.name < b.name) : (a.mark < b.mark); }
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.