Reputation: 1526
I have a vector of elements std::vector<T> my_vec
. At some point in my code I assign a score for each element of the vector using an unordered map. After that, I would like to sort the vector by the scores of its elements with the minimum code possible.
I came up with this solution, define the map as follows: std::unordered_map<const T*, float> scores_map
. For score assignment, insert the score to the map as follows:
for (const auto& el : my_vec)
scores_map[&el] = calc_score(el);
Then I sort using:
std::sort(my_vec.begin(), my_vec.end(),
[&my_map](const auto& a, const auto& b){return my_map[&a] > my_map[&b];});
Is this considered a bug-free and good practice, if not any idea how to make it so?
Upvotes: 0
Views: 788
Reputation: 206617
@fas wrote in a comment:
Elements in vector are moved during sort, so their pointers also change and
scores_map
becomes invalid, isn't it?
That is correct. You should not use pointers as keys in scores_map
.
If the vector contains unique items, you may use the T
as the key type.
for (const auto& el : my_vec)
scores_map[el] = calc_score(el);
Then sort using:
std::sort(my_vec.begin(), my_vec.end(),
[&my_map](const auto& a, const auto& b){return my_map[a] > my_map[b];});
If the vector does not contain unique elements, you may use the following strategy.
my_map
.std::vector<size_t>
object that contains just indices.my_vec
.for (size_t i = 0; i < my_vec.size(); ++i )
scores_map[i] = calc_score(my_vec[i]);
// Create the vector of indices
std::vector<size_t> indices_vec(my_vec.size());
for ( size_t i = 0; i < indices_vec.size(); ++i )
{
indices_vec[i] = i;
}
// Sort the vector of indices
std::sort(indices_vec.begin(), indices_vec.end(),
[&my_map](size_t a, size_t b){return my_map[a] > my_map[b];});
for (auto index : indices_vec)
{
// Use my_vec[index]
}
Upvotes: 2
Reputation: 16448
No, this not bug-free. std::sort
will change the addresses of the elements.
You could store the score with each element in a pair:
std::pair<float, T>
and sort the vector
std::vector<std::pair<float, T> > my_vec
with
std::sort(my_vec.begin(), my_vec.end(),
[](const auto& a, const auto& b){return a.first > b.first;});
Upvotes: 2