通过元素指针的无序映射作为键对向量进行排序
Posted
技术标签:
【中文标题】通过元素指针的无序映射作为键对向量进行排序【英文标题】:Sorting a vector by unordered map of the elements pointers as keys 【发布时间】:2020-04-07 16:11:20 【问题描述】:我有一个元素向量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];);
这是否被认为是一种没有错误的良好做法,如果不知道如何做到这一点?
【问题讨论】:
vector 中的元素在排序过程中被移动,所以它们的指针也会改变,scores_map
变得无效,不是吗?我认为没有比排序std::vector<std::pair<T, float>>
更好的方法了
哎哟。你完全正确。
【参考方案1】:
@fas 在评论中写道:
vector 中的元素在排序过程中会移动,所以它们的指针也会改变,
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]
【讨论】:
【参考方案2】:不,这不是没有错误的。 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;);
【讨论】:
请注意,如果可以比较T
,则无需传递lambda,对按字典顺序排序
将元素本身用作键会被认为是一个好的解决方案还是有点矫枉过正?
你的类需要一个散列函数,也许还需要一个键比较函数。你的班级有散列函数吗?如果是,你可以使用它以上是关于通过元素指针的无序映射作为键对向量进行排序的主要内容,如果未能解决你的问题,请参考以下文章