按照键的优先级的指定顺序按值对映射进行排序

时间:2016-11-15 09:14:13

标签: c++ algorithm sorting stdmap

我有三个整数

的地图
std::map<string,int> map1;

map1["ymax"]=10;
map1["ymin"]=16;
map1["xval"]=10;

std::map<string,int> map2;

map2["ymax"]=16;
map2["ymin"]=20;
map2["xval"]=28;

std::map<string,int> map3;

map3["ymax"]=16;
map3["ymin"]=20;
map3["xval"]=10;

并且地图包含此地图

std::map<string,std::map<string,int>> almap;

allmap["map1"]=map1;
allmap["map2"]=map2;
allmap["map3"]=map3; 

我想将最后一张地图排序为内部地图中的键ymin,但如果在大地图中保持相等的地图,我想将其排序为键xval,然后作为键{{1}同样的想法

正确排序ymax

2 个答案:

答案 0 :(得分:0)

出于教育目的......

std::map要求键/值对中的键是不变的。它还要求密钥完全描述订购。

如果是allmap,则提供的密钥为std::string,即使使用复杂的自定义比较功能,也必须继续使用该地图。

为了允许任何类型的排序,我们需要将外部名称和它们所代表的地图都滚动到一个关键对象中,然后对其进行排序。

这开始争论要么使用一组对象(因为现在没有关联的数据),要么保留一个单独的,排序的键索引,按我们的自定义谓词排序。

以下是后者:

#include <string>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <algorithm>

struct by_keys
{
  template<class...Keys>
  by_keys(std::map<std::string, std::map<std::string, int>> const& allmap, Keys&&...keys) 
    : keys_ { std::forward<Keys>(keys)... }
  , allmap_(allmap)
  {
  }

  bool operator()(const std::string& ls, const std::string& rs) const
  {
    auto& l = allmap_.find(ls)->second; 
    auto& r = allmap_.find(rs)->second; 
    for (auto& key : keys_)
    {
      auto const& il = l.find(key);
      auto const& ir = r.find(key);
      if (il == std::end(l) && ir == std::end(r)) return false;
      if (il == std::end(l) && ir != std::end(r)) return true;
      if (il != std::end(l) && ir == std::end(r)) return false;
      if (*il < *ir) return true;
      if (*ir < *il) return false;
    }
    return false;
  }

  std::vector<std::string> keys_;
  std::map<std::string, std::map<std::string, int>> const& allmap_;
};

int main()
{
std::map<std::string,int> map1;

 map1["ymax"]=10;
 map1["ymin"]=16;
 map1["xval"]=10;

std::map<std::string,int> map2;

 map2["ymax"]=16;
 map2["ymin"]=20;
 map2["xval"]=28;

std::map<std::string,int> map3;

map3["ymax"]=16;
map3["ymin"]=20;
map3["xval"]=10;

std::map<std::string,std::map<std::string,int>> allmap;

allmap["map1"]=map1;
allmap["map2"]=map2;
allmap["map3"]=map3; 

  // ok, now lets make an index into this map

  std::vector<std::string> sorted_keys;
  for (auto& entry : allmap) { sorted_keys.push_back(entry.first); }
  std::sort(std::begin(sorted_keys), std::end(sorted_keys), 
            by_keys(allmap, "ymin", "xval", "ymax"));

  // sorted_keys should now contain the names "map1", "map3", "map2" 
}

答案 1 :(得分:0)

创建所有地图的矢量,并按照密钥指定优先级的顺序tie按键对其进行排序

vector<map<string,int>> v{map1, map2, map3};

std::sort(v.begin(), v.end(), [](std::map<string,int> &lhs, std::map<string,int> &rhs){
                                 return tie(lhs["ymax"], lhs["ymin"], lhs["xval"]) < 
                                        tie(rhs["ymax"], rhs["ymin"], rhs["xval"]);}
          );

Live Demo