【问题标题】:Map comparator using child element values使用子元素值映射比较器
【发布时间】:2015-06-30 18:20:03
【问题描述】:

我有一张由以下声明的地图:

std::map<std::string, std::map<std::string, std::string>> groupList;

我想使用子地图中的值对主地图进行排序(在本例中为“序列”。例如,如果地图最初看起来像这样(键与 groupID 相同):

(
    [1] => 
        (
            [groupID] => 1
            [sequence] => 0
            [command] => DefaultState
        )

    [2] => 
        (
            [groupID] => 2
            [sequence] => 2
            [command] => Restart
        )

    [3] =>
        (
            [groupID] => 3
            [sequence] => 1
            [command] => Beep
        )

)

我希望使用此比较器后的结果如下所示:

(
    [1] => 
        (
            [groupID] => 1
            [sequence] => 0
            [command] => DefaultState
        )

    [3] =>
        (
            [groupID] => 3
            [sequence] => 1
            [command] => Beep
        )

    [2] => 
        (
            [groupID] => 2
            [sequence] => 2
            [command] => Restart
        )

)

我曾问过一个类似的问题,但不是针对在定义地图时使用比较器功能。我的其他问题的解决方案涉及使用 Boost 库和表。我想保持这个相当简单,并使用我上面的定义。

不同的选项是使用序列值作为父映射的键,这可以做到,但我想将其用作最后一个选项。地图的顺序不能改变吗?我对 C++ 的这种思维方式很陌生,因为我很新,而且很难从像这样更容易的新语言中来。

提前致谢。

【问题讨论】:

  • 你应该放弃对事物的 PHP 视图并为 C++ 数据结构建模
  • @DieterLücking 我知道,你是对的,但它比听起来要困难得多。我在做这个工作。如何在纸上为地图建模?

标签: c++ sorting dictionary


【解决方案1】:

我同意@Slava 关于不为此目的使用地图的观点。

我的建议是使用一个简单的向量,并根据不同的规则对其进行排序。像这样的:

std::vector<std::tuple<std::string, std::string, std::string>> GroupList ;

GroupList glist ;
std::sort(glist.begin(), glist.end(), mysort<0>) ;

在哪里

template <int N>
bool mysort(const std::tuple<std::string, std::string, std::string> &lhs,
            const std::tuple<std::string, std::string, std::string> &rhs)
{
   return std::get<N>(lhs) < std::get<N>(rhs.get) ;
}

然后您可以通过 std::lower_bound 快速访问向量中的对象,并在需要时根据例如重新排序向量mysort&lt;1&gt;

【讨论】:

    【解决方案2】:

    虽然技术上可以根据值而不是键对std::map 进行排序,但我强烈不建议这样做,因为它会导致错误并且很难支持代码。 std::map 的键是不可变的,它遵循 std::map 设计,如果你在值上使用比较器并修改它,你会得到不可预测的行为。您可以改用std::set

    typedef std::map<std::string,std::string> Group;
    struct GroupComp {
         bool operator()( const Group &g1, const Group G2 ) const { ... }
    };
    typedef std::set<Group, GroupComp> GroupList;
    

    Group 内的GroupList 仍然是不可变的,因此要修改元素,您必须删除并重新插入修改后的副本。如果这不是您想要的,您可能可以将Group 存储在std::vectorstd::list 等中并建立一个外部索引——实际上是在boost::multi_index 中完成的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-13
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多