There are a couple possible ways to do this. The easiest way is to wrap name
, x
, and y
in a struct:
struct Person {
std::wstring name;
int x;
int y;
};
Then you can have a std::vector<Person> people
and sorting it would be (assuming C++14)
std::sort(people.begin(), people.end(),
[](auto const& lhs, auto const& rhs) { return lhs.name < rhs.name; });
However, if you know that this will cause performance problems due to fewer elements fitting in the cache (that is, you'd frequently iterate over only x
or only y
and you are in a very constrained environment such as high performance gaming), I'd suggest only sorting one vector. Unless you know what you're doing, you'd need to benchmark both options.
Basically, have a vector that keeps track of the ordering:
std::vector<std::wstring> name;
std::vector<int> x;
std::vector<int> y
std::vector<std::size_t> ordering(name.size());
std::iota(ordering.begin(), ordering.end(), 0);
std::sort(ordering.begin(), ordering.end(),
[&](auto const& lhs, auto const& rhs) {
return name[lhs] < name[rhs];
});
Then you can simply iterate over ordering
to go through each parallel vector in the new order.
It's possible that the extra level of indirection will make it less efficient. For example, the CPU might think that there's a data dependency where there is none. Furthermore, the extra data we are keeping track of in ordering
could easily take enough room in the cache to counteract the benefit of separating name
, x
, and y
; you'd need to know the specifications of your target architecture and profile to be sure.
If you would want to keep iterating over them in this new order, you would want to use this ordering
vector to sort the other vectors, because the access to the elements would become random. That would counteract the benefit of keeping the vectors separate (unless the vectors are small enough to fit in the cache anyway).
The easiest way to do that would be to create a new vector:
std::vector<std::wstring> newNames;
newNames.reserve(name.size());
for (auto i : ordering) {
newNames.push_back(name[i]);
}
Reconstructing the vectors like this is probably what you want to do if the sorting happens during initialization.