【问题标题】:Can STL or Boost help sort a map by value?STL 或 Boost 能否帮助按值对地图进行排序?
【发布时间】:2017-10-15 21:06:22
【问题描述】:

标题中的“排序”一词在这里可能会产生误导。我正在寻找这种行为:

{ 1: 100,               { 1: 1,
  3: 10,        =>        3: 10,
  5: 1000,                5: 100,
  9: 1 }                  9: 1000 }

也就是说,按升序将值重新分配给现有键。

这对临时来说并不难:

using K = int;
using V = int;
std::map<K, V> myMap{ {1, 100}, {3, 10}, {5, 1000}, {9, 1} };
std::vector<V> tempVec; // insert map values into vector
std::transform(myMap.begin(), myMap.end(), std::back_inserter(tempVec),
               [](auto const& mapPair) { return mapPair.second; });
std::sort(tempVec.begin(), tempVec.end());
size_t i = 0;
for (auto& mapPair : myMap) {
    mapPair.second = tempVec[i++];
}

这可以简化甚至更好地完成吗?

【问题讨论】:

  • 从技术上讲,如果键或值是用户定义的类型,您可以为映射的value_type 重载 std::swap(如果它们依赖,您可以在 std:: 命名空间中添加重载在使用定义的类型上)仅交换值部分,然后将 std::sort 与自定义比较器一起使用。在实践中,这不是一个好主意。
  • @Revolver_Ocelot 缺点是在需要默认行为的上下文中很难摆脱自定义重载,对吧?
  • 是的。但是,由于 map 的 value_typepair&lt;const key, value&gt;,其默认行为是 编译错误,我不认为 this 是问题所在。人们看着 std::sort 而不是 std::map 并试图弄清楚这是什么巫术,但这是一个问题。
  • 感觉像是 XY 问题。如果键不必与值一起使用,为什么要使用地图?好像你想要两个大小相等的排序向量,或者两个集合或其他东西。
  • myMap[mapPair.first] = tempVec[i++] 应该是mapPair.second = tempVec[i++]

标签: c++ sorting boost stl stdmap


【解决方案1】:

您不能按值对地图进行排序。

因为std::map 按键组织条目以完成其工作(如O(log n) 查找和插入),所以无法更改此行为。

但是,您可以使用std::set&lt;YourType&gt;,其中YourType 是一个元组(如std::pair 或如下所示的自定义类型),并且您提供自定义比较运算符,以便集合按以下方式组织价值。

struct YourType {
  int key;
  int value;
  bool operator<(const YourType& other) const { 
    return std::tie(value, key) < std::tie(other.value, other.key); 
  }
};

【讨论】:

  • OP 并不想按值对地图进行排序。他们想对map中的值进行排序,彻底打破key和value的关系。
  • 这根本不能回答问题。我不知道谁赞成这个。
  • 你是对的。但由于 Op 已经提出了一种方法来做到这一点,我建议改用不同的数据结构。
  • @crazypeter 这个数据结构的行为完全不同——它对对进行排序,而不仅仅是对值进行排序。
  • “按升序将值重新分配给现有键”的措辞让我觉得我们想要保留键和值之间的关系。抱歉,如果答案没有帮助。
【解决方案2】:

如果我们不需要高效的算法,我们可以简单地实现选择排序。

for (auto mi = myMap.begin(); mi != myMap.end(); ++mi) {
    auto const& mini = min_element(mi, myMap.end(), [](auto const& pa, auto const& pb) { return pa.second < pb.second; });
    swap(mi->second, mini->second);
}

【讨论】:

    猜你喜欢
    • 2012-08-29
    • 2012-04-25
    • 2011-02-11
    • 2019-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多