gvgramazio
gvgramazio

Reputation: 1154

Vector of pointers to objects of another vector - initialization and sorting

I have two vector. The first one is a vector of objects of some class. The second one is a vector which elements point to the objects of the first vector.

I have two question for you. The first one is: there is a better or more elegant way to declare and initialize the vector of pointers?

The second one is a bit more complex to explain. Suppose that i want to see the elements of the first vector in a descending order. All i have to do is to overload the operator < and sort them. Well, suppose now that i want to see the elements of the first vector in a descending order without change the order of its element but only with the help of the second vector. In other words, I want to sort the element of the second vector looking at what they point to and not, as usual, looking at its elements since they are addresses. What should I do? Overload the operator < with other type of arguments? Pass another order function to sort?

I give you a Minimal, Complete, and Verifiable example to compile with g++ -std=c++11 -o example example.cpp.

example.ccp

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

class MyClass{
    public:
        int a;
        int b;
        MyClass(int a, int b) : a(a), b(b){};
        bool operator<(const MyClass &obj)const{return (this->a + this->b) < (obj.a + obj.b);};
};

int main(int argc, char* argv[]){
    std::vector<MyClass> vector1;
    vector1.push_back({4, 5});
    vector1.push_back({5, 6});
    vector1.push_back({6, 7});
    vector1.push_back({1, 2});
    vector1.push_back({2, 3});
    vector1.push_back({3, 4});

    std::vector<MyClass*> vector2;
    std::vector<MyClass>::iterator i;
    for(i = vector1.begin(); i != vector1.end(); i++)
        vector2.push_back(&(*i));

    std::cout << "element pointed to by vector2 unsorted: " << std::endl;
    for(int j = 0; j < vector2.size(); j++)
        std::cout << vector2[j]->a << " " << vector2[j]->b << std::endl;        

    /* Insert here how I should sort vector2 */
    // std::sort (vector2.begin(), vector2.end());  <-- Obviously this doesn't work

    std::cout << "element pointed to by vector2 sorted: " << std::endl;
    for(int j = 0; j < vector2.size(); j++)
        std::cout << vector2[j]->a << " " << vector2[j]->b << std::endl;    


    return 0;
}

Upvotes: 0

Views: 560

Answers (1)

molbdnilo
molbdnilo

Reputation: 66451

It sounds to me like the first vector is a red herring and this would do:

bool compare(const MyClass* lhs, const MyClass* rhs)
{
    return *lhs < *rhs;
}

std::sort (vector2.begin(), vector2.end(), compare);

A more stable variant in the presence of modifications to vector1 is to store indexes instead of pointers:

std::vector<size_t> vector2(vector1.size());
std::iota(vector2.begin(), vector2.end(), 0);

std::sort (vector2.begin(), 
           vector2.end(), 
           [&](int l, int r) { return vector1[l] < vector1[r]; });

std::cout << "element pointed to by vector2 sorted: " << std::endl;
for(int j = 0; j < vector2.size(); j++)
    std::cout << vector1[vector2[j]].a << " " << vector1[vector2[j]].b << std::endl;

Upvotes: 1

Related Questions