Sort a vector of objects

Hi!

I have several pointers to objects in a vector to be sorted. I think I can use sort(myVector.begin(),myVector.end()) but this method sort by pointer memory directions.

I have an object called Vehicle with an int price. So I'd like to sort the vehicles by price.

Is there any method to use sort and tell it to sort by the objects instead of sorting by the pointers of the vectors ?

Many Thanks!

Enric
EM77Asked:
Who is Participating?
 
itsmeandnobodyelseCommented:
class Vehicle {

public:
  static int lastCounter;

   Vehicle(int pr) : counter(++lastCounter), price(pr) {}

   int GetPrice () const { return price;}

   int GetCount() const  { return counter;}

   static bool lessPrice(const Vehicle*& pv1, const Vehicle*& pv2)
   {
        return pv1.GetPrice() < pv2->GetPrice();
   }
   static bool lessCount(const Vehicle*& pv1, const Vehicle*& pv2)
   {
        return pv1.GetCount() < pv2->GetCount();
   }

private;

    int counter;
    int price;
   
};

int main()
{
     vector<Vehicle*> vVehicles;
     vVehicles.push_back(pVehicle1); //pVehicle->price = 1000
     vVehicles.push_back(pVehicle2); //pVehicle->price = 3000
     vVehicles.push_back(pVehicle3); //pVehicle->price = 2000
     sort<vVehicles.begin(), vVehicles.end(), Vehicle::lessPrice);
     for (int i = 0; i < arr.size(); ++i)
        cout << vVehicles[i]->GetCount() << '|' << vVehicles[i]->GetPrice() << endl;
     sort<vVehicles.begin(), vVehicles.end(), Vehicle::lessCount);
     for (int ii = 0; ii < vVehicles.size(); ++ii)
        cout<< vVehicles[ii]->GetCount()  << '|'   << vVehicles[ii]->GetPrice()  << endl;

    return 0;
};

0
 
jkrCommented:
>>I have an object called Vehicle with an int price. So I'd like to sort the vehicles by price.

All you need to do is to provide an predicate object that takes care of the comparison, e.g.

class Vehicle {

public:

int GetPrice () const { return price;}

private;

int price;
};

struct greater_VehiclePtr : public greater<Vehicle*> {
public:
  bool operator()(Vehicle* pl, Vehicle* pr) { return pl->GetPrice() > pr->GetPrice(); }
};

vector<Vehicle*> vVehicles;

//...

sort(vVehicles.begin(), vVehicles.end(), greater_VehiclePtr());
0
 
EM77Author Commented:
Where do you define the greater_VehiclePtr? Inside the Vehicle hearder??¿?¿?
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
jkrCommented:
That would be one possible place. As a rule of thumb: Define it where you need it. The following demostrates the whole thing:

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

class Vehicle {

public:

int GetPrice () const { return price;}

private:

int price;
};

struct greater_VehiclePtr : public greater<Vehicle*> {
public:
  bool operator()(Vehicle* pl, Vehicle* pr) { return pl->GetPrice() > pr->GetPrice(); }
};

int main () {

vector<Vehicle*> vVehicles;

//...

sort(vVehicles.begin(), vVehicles.end(), greater_VehiclePtr());

return 0;
}
0
 
EM77Author Commented:
Ok, It works!!!!

Now I have another problem. First of all I have to list the objects sorted by price, then I have to list it as they were created.

When I wrote sort(......) my vVector is modified so then I'd like to set it as it was created...

Any idea???

Many Thanks!

Enric
0
 
jkrCommented:
>>I have to list it as they were created.

What do you mean?
0
 
itsmeandnobodyelseCommented:
That works at my system (VC6/XP):

class A
{
public:
    string a;
    A(const char* s) : a(s) {};

};


bool Aless(const A*& pa1, const A*& pa2)
{
    return pa1->a < pa2->a;
}

class A
{
public:
    string a;
    A(const char* s) : a(s) {};

    static bool less(const A*& pa1, const A*& pa2)
    {
        return pa1->a < pa2->a;
    }
};

int main()
{
    vector<A*> arr;
    A a1("John");
    A a2("James");
    A a3("Bill");
    arr.push_back(&a1);
    arr.push_back(&a2);
    arr.push_back(&a3);
    sort(arr.begin(), arr.end(), A::less);

    for (int ii = 0; ii < arr.size(); ++ii)
        cout << arr[ii]->a << endl;

    return 0;
};

It passes a substitute to the built-in operator< function that could be defined for class types only.

Regards, Alex
0
 
itsmeandnobodyelseCommented:
That part needs to removed:

class A
{
public:
    string a;
    A(const char* s) : a(s) {};

};


bool Aless(const A*& pa1, const A*& pa2)
{
    return pa1->a < pa2->a;
}

>>>>  I'd like to set it as it was created...

You need to add a member that counts :

class Vehicle
{
    static int lastCounter;
    int counter;
    int price;
public:
    Vehicle(int pr) : counter(++lastCounter), price(pr) {}
    ...
};


// vehicle.cpp

#include "vehicle.h"

// initialize counter
int Vehicle::lastCounter = 0;


With that you could define a further sort function that goes for counter rather than for price.

Regards, Alex
0
 
EM77Author Commented:
First of all I'm adding pointer to vector as I show:

vVehicles.push_back(pVehicle1); //pVehicle->price = 1000
vVehicles.push_back(pVehicle2); //pVehicle->price = 3000
vVehicles.push_back(pVehicle3); //pVehicle->price = 2000

1.-Now I use your code and I list all vehicles in vector so they're showed sorted

pVehicle2
pVehicle3
pVehicle1

2.- Now I need to show all vehicles (without using your sort method) as I pushed_back in vector, so I need to show  as I've created the object.
The result need to be:

pVehicle1
pVehicle2
pVehicle3

But I'm showing it from the first place of the vector to the end and the result is the same as sorted vehicles. I understand that when we sort vehicles we are modifying the vector so when I'm trying to show as I've created the vehicles it is shown incorrect.

Sorry but my english is not as good as I'd like ! ;)

Thanks
0
 
itsmeandnobodyelseCommented:
>>>> int Vehicle::lastCounter = 0;

I forgot to initialize the static member.

Regards, Alex
0
 
jkrCommented:
>>Now I need to show all vehicles (without using your sort method) as I pushed_back in vector

Just do that before you sort them or create a copy of the vector, e.g.

vector<Vehicle*> vVehicles;

//...
vector<Vehicle*> vVehiclesInAddingOrder = vVehicles;

sort(vVehicles.begin(), vVehicles.end(), greater_VehiclePtr());
0
 
AxterCommented:
I recommend using smart pointers instead of raw dummy pointers in an STL container.

Moreover, if you use the following smart pointer, it will let you sort by the object instead of the object pointer address.
http://axter.com/smartptr

You can declare it like so:

vector<smart_ptr<Vechicle> > vVehicles;

If you which to use a more simplistic smart pointer, you can use the following:
http://code.axter.com/copy_ptr.h

The copy_ptr also has value semantics for the comparison operator instead of pointer semantics.

By using a smart pointer with value semantics, you get safer code, and it makes it easier to do sorting in STL containers.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.