Home > Software design >  How do I compare 2 objects if they have three values to be tested against? [duplicate]
How do I compare 2 objects if they have three values to be tested against? [duplicate]

Time:10-01

I'm writing a less than and equal operator function for a class object.

The three variables that are apart of the class are

string firstName;
string LastName;
int age;

To compare them, I wrote this operator function:

bool person::operator < (person b)
{
    if (firstName < b.firstName && lastName < b.lastName && age < b.age)
        return true;
    else
        return false;
}

However, my code doesn't work and I don't understand why.

When comparing the objects, priority goes to lastName, firstName, then age.

So, Bill Gates 43 would be technically less than Bill Gates 44.

I hope that is clear enough.

CodePudding user response:

Here's my version of the comparison:

bool person::operator< (const person& b)
{
    if (lastName != b.lastName)
    {
        return lastName < b.lastName;
    }
    if (firstName != b.firstName)
    {
        return firstName < b.firstName;
    }
    return age < b.age;
}

If one field is equal to the object, then the next field is compared. Otherwise the method compares the two fields for less than.

CodePudding user response:

Your comparison logic is wrong. You should write something like:

bool person::operator<(person b) {
    if (lastName < b.lastName) {
        return true;
    } else if (lastName > b.lastName) {
        return false;
    }

    if (firstName < b.firstName) {
        return true;
    } else if (firstName > b.firstName) {
        return false;
    }

    if (age < b.age) {
        return true;
    }

    return false;
}

CodePudding user response:

Here is a solution using std::tie

It makes writing comparison operators like this very simple and very hard to get wrong.

#include <algorithm>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>

struct Person
{
    std::string firstName;
    std::string lastName;
    int age;

    bool operator<(const Person &other) const
    {
        return std::tie(lastName, firstName, age)
            < std::tie(other.lastName, other.firstName, other.age);
    }
};

void print(const std::string& title, const std::vector<Person> &people)
{
    std::cout << title << "\n";
    for (const Person &person : people)
    {
        std::cout << person.lastName << ", " 
            << person.firstName << ", " 
            << person.age << "\n";
    }
}

int main()
{
    std::vector<Person> people {
        { "Bill", "Gates", 44 },
        { "Gates", "Bill", 44 },
        { "Back", "Gates", 43 },
        { "Front", "Gates", 44 },
        { "Bill", "Gates", 43 },
        { "Gates", "Bill", 43 },
        { "Back", "Gates", 44 },
        { "Front", "Gates", 43 },
    };

    print("Before Sort:", people);
    std::sort(people.begin(), people.end());
    print("After Sort:", people);

    return 0;
}

Online example: https://ideone.com/YFnEdB

Output:

Before Sort:
Gates, Bill, 44
Bill, Gates, 44
Gates, Back, 43
Gates, Front, 44
Gates, Bill, 43
Bill, Gates, 43
Gates, Back, 44
Gates, Front, 43
After Sort:
Bill, Gates, 43
Bill, Gates, 44
Gates, Back, 43
Gates, Back, 44
Gates, Bill, 43
Gates, Bill, 44
Gates, Front, 43
Gates, Front, 44

CodePudding user response:

Your code doesn't work for Bill Gates 43 and Bill Gates 44, because you are only using less than operator here and Bill < Bill will return false which makes the entire if statement false.

bool person::operator < (const person& b) //Always pass your object as reference
{
    if (firstName <= b.firstName && lastName <= b.lastName && age < b.age)
        return true;
    else
        return false;
}

Now it will work for the example you gave. But a better way of doing this would be like this considering you want to compare all three attributes in given order.

bool person::operator < (const person& b)
{
     if (lastName != b.lastName)
       {
         return lastName < b.lastName;   
       }     
    else if(firstname != b.firstName)
       {
            return firstname < b.firstName;
       }
      else
         return age < b.age;
         
    return false;
}
  •  Tags:  
  • c
  • Related