0

There are structs like these


class Component {
    string name;
    int x;
    int y;
};

struct Relation_h { // also for Relation_v (h for horizontal, v for vertical)
    Component *;
    //some data in here;
};

I have a initial vector vector<Component> data and vector<list<Relation>> relation_h and relation_v

I want to sort the vector data corresponding to its x and y respectively then construct the relations
and the Component* actually points to the data[i] for i in range(0, data.size())

But the problem is that the pointer points to is not the original object which I want to access after sorting with x and y

Is there way to deal with this situation?

  • Probably the trick is not to try and sort the data itself. [See this](https://stackoverflow.com/questions/46382252/sort-array-by-first-item-in-subarray-c/46382976#46382976). In short, have an index array and sort that instead, based on the original sort criteria. Then use the index array to access the elements in a sorted manner. And also, please post a [mcve] -- we have no idea what you're doing when you say you're sorting the data. – PaulMcKenzie Jul 11 '21 at 07:01
  • Also, there is no need for pointers here. You have a vector of objects -- where would anything to do with pointers be relevant? Maybe it's because you didn't think of doing things in the way I suggested in the first comment? – PaulMcKenzie Jul 11 '21 at 07:04
  • @PaulMcKenzie Thanks for answer, the reason I want to sort the data is that when I construct the relation_h or relation_v just for convinient of push_back directly – young03600 Jul 11 '21 at 07:06
  • Well, I can't easily post an answer to code that isn't shown. However from your description, using an index array and sorting that would seem to accomplish your goal easily. – PaulMcKenzie Jul 11 '21 at 07:08
  • the vector data is the name of vector, sorry for that – young03600 Jul 11 '21 at 07:09
  • 1
    Please don't edit answers into the question, if you've solved your problem you can post an answer to your own question – Alan Birtles Jul 11 '21 at 07:19
  • An array with pointers to the elements of the `data` vector is in most cases easier to use than an index array. Btw: technically it's not the adresses of objects that change, but the data in the existing objects is swapped... – fabian Jul 11 '21 at 07:23
  • @fabian I understand that technically , thanks for remind that, I will revise the post – young03600 Jul 11 '21 at 07:28

1 Answers1

1

One such solution (but of course, not the only one) as mentioned in the comments is to use an auxiliary index array as described in this answer

#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <numeric>

//...
struct Component {
    std::string name;
    int x;
    int y;
    Component(int val1, int val2) : x(val1), y(val2) {}
};
//...
int main()
{
    std::vector<Component> vComponents = { {2,3},{1,2},{0,2},{12,-2},{3,4},{-6,1} };

    // Create the index array (0,1,2,3,4,...)
    std::vector<int> index(vComponents.size());
    std::iota(index.begin(), index.end(), 0);

    //Print original
    std::cout << "Original order:\n";
    for (auto i : index)
        std::cout << vComponents[i].x << " " << vComponents[i].y << "\n";

    // Sort the index array, based on the x, y criteria
    std::sort(index.begin(), index.end(), [&](int n1, int n2)
        { return std::tie(vComponents[n1].x, vComponents[n1].y) <
                 std::tie(vComponents[n2].x, vComponents[n2].y); });
    //...
    // Print sorted
    std::cout << "\nSorted order:\n";
    for (auto i : index)
        std::cout << vComponents[i].x << " " << vComponents[i].y << ":    Location is at " << i << "\n";
}

Output:

Original order:
2 3
1 2
0 2
12 -2
3 4
-6 1

Sorted order:
-6 1:    Location is at 5
0 2:    Location is at 2
1 2:    Location is at 1
2 3:    Location is at 0
3 4:    Location is at 4
12 -2:    Location is at 3

There are a few things to note:

  1. The index array is the array that's sorted. The indices given to the std::sort predicate are used for the comparison within the vComponents vector.

  2. The usage of std::tie makes it trivial to compare "cascading" members, such as x and then y.

You then use the index array to access the elements. You keep the order of the elements intact, but have the index array that indicates where the "sorted" item is located.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45