我有一张由以下声明的地图:
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 ++的这种思维方式不熟悉,因为我很新,而且很难从更新的语言中获得这样的东西。
提前致谢。
答案 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::vector
或std::list
等中并构建一个外部索引 - 实际上在boost::multi_index
内做了什么。