Rome_Leader
Rome_Leader

Reputation: 2700

Sorting Multiple Objects By Member in Descending Order?

I've had a look at the following question : Sorting a vector of objects by a property of the object

And it seems very relevant to my case. I have a small number of Player objects (6-10), and they all have information such as their name, and several relevant stats. I want to sort them in descending order by one particular stat.

Still very confused about what the

Help please!

EDIT: FULL UPDATED CODE BELOW

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

using namespace std;

 class Player {
 public:
Player(string name, int Dex, int Mod, int Lvl, int& diceRoll);

int calcInitiative(int& diceRoll);

int diceRoll;

friend ostream& operator<<(ostream& out, const Player& player) {
    return out << player.mName << " " << player.mInitiative; 
    }

bool operator<(const Player& rhs) const {

 if(mInitiative < rhs.mInitiative) return true;

     if(mInitiative > rhs.mInitiative) return false;

     if(mInitiative == rhs.mInitiative) return false;

}

int mDex, mMod, mLvl, mInitiative;
 string mName;
 };

Player::Player(string name, int Dex, int Mod, int Lvl, int& diceRoll)
: mName(name), mDex(Dex), mMod(Mod), mLvl(Lvl)
{}


 int Player::calcInitiative(int& diceRoll) {

return (mLvl/2) + mDex + mMod + diceRoll;
 }

 int main() {

 int rollD, rollS; // etc.

 vector<Player> playerVec;

 cout << "Derek rolled: ";
 cin >> rollD;
 cout << '\n' << "Scott rolled: ";
 cin >> rollS;

// etc.


Player Derek("Derek", 2, 0, 6, rollD);
Player B("B", 2, 0, 9, rollB);

// etc...

Derek.mInitiative = Derek.calcInitiative(rollD);
Scott.mInitiative = Scott.calcInitiative(rollS);

//etc.

playerVec.push_back(Derek);
playerVec.push_back(Scott);

// etc.

cout << "The initative order is: " << '\n';

sort (playerVec.begin(), playerVec.end());

for(vector<Player>::iterator it = playerVec.begin(); it != playerVec.end(); ++it) {
cout << *it << endl;
}

system("pause");

return 0;
}

Upvotes: 1

Views: 210

Answers (2)

Rick Yorgason
Rick Yorgason

Reputation: 1666

You almost have all the code written already.

In your Player class, add the following function:

bool operator<(const Player& rhs) const;

and make it return true if this is less than the right-hand-side. Similar to your last code block.

Now run:

sort(myVec.begin(), myVec.end());

That will do an in-place sort.

Edit: Here's a fully compilable example to show how it all works together:

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

class Player
{
public:
        Player(int stat1, int stat2) : m_stat1(stat1), m_stat2(stat2) {}

        bool operator<(const Player& rhs) const {
                if(m_stat1 < rhs.m_stat1) return true;
                if(m_stat1 > rhs.m_stat1) return false;
                return m_stat2 < rhs.m_stat2;
        }

        friend ostream& operator<<(ostream& out, const Player& player) {
                return out << player.m_stat1 << ", " << player.m_stat2;
        }

private:
        int m_stat1, m_stat2;
};

int main()
{
        vector<Player> aPlayers;
        aPlayers.push_back(Player( 1, 2 ));
        aPlayers.push_back(Player( 1, 1 ));
        aPlayers.push_back(Player( 5, 0 ));

        std::sort(aPlayers.begin(), aPlayers.end());

        for(vector<Player>::iterator it = aPlayers.begin();
                        it != aPlayers.end(); ++it)
        {
                cout << *it << endl;
        }
}

Outputs:

1, 1
1, 2
5, 0

I put operator<< in there since you mentioned it in your comment, but it really has nothing to do with sorting. std::sort() will work just fine without it.

Edit 2: With your new code, you mention that the compiler is giving you an error. That error is likely because it can't be certain that the code will return a value. If you add return false to the end of operator<, it will stop giving you an error. That would also make the third line in your operator< redundant.

As far as the results being in reverse order, sort sorts in ascending order by default. There's a couple really simple ways to resolve this. The most obvious is to rewrite operator< to generate the ordering your would prefer. A more general option is to feed reverse iterators into std::sort instead of the default iterators:

std::sort(aPlayers.rbegin(), aPlayers.rend());

rbegin() and rend() are just like begin() and end(), except they go in reverse.

Upvotes: 2

Samuel
Samuel

Reputation: 6490

By calling std::sort on a vector with a provided predicate (in your case this is a functor) you are already swapping your players.

In your sample after calling sort on myVec you will have your vector of of Player, or what ever T is sorted by the property x in a descending order.

So I see no purpose of switching / swapping anything manually.

Upvotes: 2

Related Questions