我有一个元素std::vector<T> my_vec
的向量。在我的代码中的某个时刻,我使用无序映射为向量的每个元素分配一个分数。在那之后,我想用可能的最小代码,根据向量元素的分数对向量进行排序。
我提出了这个解决方案,定义映射如下:std::unordered_map<const T*, float> scores_map
。对于分数分配,将分数插入地图,如下所示:
for (const auto& el : my_vec)
scores_map[&el] = calc_score(el);
然后我使用进行排序
std::sort(my_vec.begin(), my_vec.end(),
[&my_map](const auto& a, const auto& b){return my_map[&a] > my_map[&b];});
如果不知道如何做到这一点的话,这是否被认为是一种没有错误的良好做法?
@fas在评论中写道:
矢量中的元素在排序过程中被移动,所以它们的指针也会发生变化,
scores_map
也会无效,不是吗?
这是正确的。您不应该在scores_map
中使用指针作为键。
选项1
如果矢量包含唯一项,则可以使用T
作为键类型。
for (const auto& el : my_vec)
scores_map[el] = calc_score(el);
然后使用进行排序
std::sort(my_vec.begin(), my_vec.end(),
[&my_map](const auto& a, const auto& b){return my_map[a] > my_map[b];});
选项2
如果矢量不包含唯一元素,则可以使用以下策略。
- 使用索引作为
my_map
的密钥 - 创建一个仅包含索引的辅助对象
std::vector<size_t>
- 对索引的矢量进行排序
- 使用排序后的索引向量从
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]
}
不,这不是没有错误的。std::sort
将改变元素的地址。
你可以将每个元素的分数存储在一对中:
std::pair<float, T>
并对矢量进行排序
std::vector<std::pair<float, T> > my_vec
带有
std::sort(my_vec.begin(), my_vec.end(),
[](const auto& a, const auto& b){return a.first > b.first;});