使用子元素值映射比较器

时间:2015-06-30 18:20:03

标签: c++ sorting dictionary

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

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

我想使用子映射中的值对此主映射进行排序(在本例中为“sequence”。例如,如果映射最初看起来像这样(键与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 ++的这种思维方式不熟悉,因为我很新,而且很难从更新的语言中获得这样的东西。

提前致谢。

2 个答案:

答案 0 :(得分: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<1>

答案 1 :(得分:0)

虽然从技术上讲,可以根据值而不是密钥对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内做了什么。