[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
Solved

Sort a vector of objects

Posted on 2006-04-13
Medium Priority
397 Views
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
0
Question by:EM77
• 4
• 4
• 3
• +1

LVL 86

Expert Comment

ID: 16447114
>>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

Author Comment

ID: 16447161
Where do you define the greater_VehiclePtr? Inside the Vehicle hearder??Â¿?Â¿?
0

LVL 86

Expert Comment

ID: 16447214
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

Author Comment

ID: 16447475
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

LVL 86

Expert Comment

ID: 16447492
>>I have to list it as they were created.

What do you mean?
0

LVL 39

Expert Comment

ID: 16447508
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

LVL 39

Expert Comment

ID: 16447561
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

Author Comment

ID: 16447584
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

LVL 39

Accepted Solution

itsmeandnobodyelse earned 336 total points
ID: 16447728
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

LVL 39

Expert Comment

ID: 16447748
>>>> int Vehicle::lastCounter = 0;

I forgot to initialize the static member.

Regards, Alex
0

LVL 86

Assisted Solution

jkr earned 332 total points
ID: 16447986
>>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

LVL 30

Assisted Solution

Axter earned 332 total points
ID: 16449247
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

Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deletiâ€¦
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticallâ€¦
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Botâ€¦
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses
Course of the Month17 days, 16 hours left to enroll

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.