1

In STL, list is a data structure that automatically sort the numbers by their values. If the elements are not numbers but instances of a class, and I want the container to automatically sort the elements by the value of a member of the class, what kind of container should I use? e.g.

class Rect{
    double height;
    double width;
    double area;
};

I want the container to automatically sort by area of the rectangle.

Patrick Fournier
  • 600
  • 6
  • 19
daydayup
  • 2,049
  • 5
  • 22
  • 47
  • http://stackoverflow.com/questions/5174115/sorting-a-vector-of-objects-by-a-property-of-the-object – Untitled123 Dec 27 '15 at 03:25
  • 1
    "In STL, list is a data structure that automatically sort the numbers by their values." really? [`std::list`](http://www.sgi.com/tech/stl/List.html) won't do such a thing. What do you mean by "STL"? – MikeCAT Dec 27 '15 at 03:26
  • 2
    STD is an obsolete acronym of Standard Template Library. No `std::list` does not automatically sort elements. For that you need `std:set`. – ThomasMcLeod Dec 27 '15 at 03:58

5 Answers5

4

You have std::multiset for auto-ordering container:

std::multiset<Rect, LessArea> rects;

with LessArea

struct LessArea
{
    bool operator ()(const Rect& lhs, const Rect& rhs) const
    {
        return lhs.area < rhs.area;
    }
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
3

stl::priority_queue is what you want. Just define an ordering on Rects with less<Rect> or specialize stl::priority_queue for Rect.

Patrick Fournier
  • 600
  • 6
  • 19
2

If you want to sort automatically , you have to do what is called

1) Operator Overloading of less than < operator

2) Comparator function

And for your task , to automatically sort , AFTER you have written a comparison function or overloaded the < operator , You can use either

STL set or priority queue . These two data structures are defined to automatically sort the elements based on the comparison function. But a note here is that you can't insert duplicate elements in set , that is if area of your two rectangle is same , then the first one of those rects will be saved in the set. And second one can't be inserted.

Tamim Addari
  • 7,591
  • 9
  • 40
  • 59
1

Program using std::set will look like below .

class Rect{
    double height;
    double width;
    double area;

public:
    bool operator<( const Rect& rhs ) const
        { return area < rhs.area; }
};

You need to define "<" operator for comparison . Please note : std::set will not allow multiple copies of same object .you can have only unique elements inside set .

SACHIN GOYAL
  • 955
  • 6
  • 19
1

I don't mind using a vector, especially if you want to be able to store duplicate elements. By using a simple lambda function, we can sort the objects by whatever member of a Rect we want. In this example, I chose to sort Rect objects by area.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Rect {
    Rect(double height, double width, double area) {
        _height = height;
        _width = width;
        _area = area;
    }

    double area() const {
        return _area;
    }

    // sorts Rect objects by ascending order of area
    static void sort_by_area(vector<Rect> &shapes) {
        sort(shapes.begin(), shapes.end(), [](const Rect &first, const Rec &second)
                                           { return first.area() < second.area); });
    }

private:
    double _height;
    double _width;
    double _area;
};

int main() {
    vector<Rect> r;
    r.push_back(Rect(0,0,3));
    r.push_back(Rect(0,0,2));
    r.push_back(Rect(0,0,4));

    for(auto &obj : r) {
        //prints 3 2 4
        cout << obj.area() << endl;
    }

    Rect::sort_by_area(r);

    for(auto &obj : r) {
        //prints 2 3 4
        cout << obj.area() << endl;
    }
    return 0;
}
ChrisD
  • 674
  • 6
  • 15