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

x
?
Solved

Sort a vector of objects

Posted on 2006-04-13
14
Medium Priority
?
397 Views
Last Modified: 2013-12-14
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
Comment
Question by:EM77
  • 4
  • 4
  • 3
  • +1
12 Comments
 
LVL 86

Expert Comment

by:jkr
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

by:EM77
ID: 16447161
Where do you define the greater_VehiclePtr? Inside the Vehicle hearder??¿?¿?
0
 
LVL 86

Expert Comment

by:jkr
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:EM77
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

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

What do you mean?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
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

by:itsmeandnobodyelse
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

by:EM77
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

by:
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

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

I forgot to initialize the static member.

Regards, Alex
0
 
LVL 86

Assisted Solution

by:jkr
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

by:Axter
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

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

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

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.

Join & Ask a Question