std::unordered_map 行为不符合预期

std::unordered_map not behaving as expected

提问人:expl0it3r 提问时间:8/13/2020 更新时间:8/14/2020 访问量:272

问:

std::unordered_map<std::string,std::string> mymap;
mymap.insert(std::make_pair("ELEMENTTYPE", "NEWINTERFACE"));
mymap.insert(std::make_pair("STYLEFILE", "Style_Light.txt"));
mymap.insert(std::make_pair("ELEMENTNAME", "IN1"));
mymap.insert(std::make_pair("POSITIONX", "0"));
mymap.insert(std::make_pair("POSITIONY", "0"));
mymap.insert(std::make_pair("SIZEX", "50"));
mymap.insert(std::make_pair("SIZEY", "50"));

我希望地图按该顺序包含这些元素,但相反,它是:

-大小

-元素类型

-样式文件

-尺寸x

-位置x

-位置

我很困惑;为什么对我的元素进行排序?std::unordered_map

C++ 字典 std 无序

评论

5赞 Ted Lyngmo 8/13/2020
unordered_map和订单 - 不是一个好的组合
0赞 expl0it3r 8/13/2020
我的印象是,它根本不会触及元素的顺序 - 它会保持元素插入序列中的样子。
0赞 expl0it3r 8/13/2020
我如何能够用标准地图订购这个?
1赞 Remy Lebeau 8/14/2020
@jasbindra00 但是,为什么地图元素的顺序对你很重要呢?您是否打算在之后将地图写回文件中,并希望保留与读入时相同的顺序?使用单独的键值,甚至是键索引对的映射,来跟踪文件中的顺序,而无需对映射本身进行排序,这很容易实现。vector
1赞 shananton 8/14/2020
另外,您提前知道字段名称(等)吗?如果这样做,请考虑将文件解析为具有所需字段的结构,而不是使用字符串映射。SIZEX

答:

0赞 Remy Lebeau 8/13/2020 #1

顾名思义,a 是无序的。其元素的顺序未指定,将取决于值的哈希值。std::unordered_mapKey

如果元素的顺序对您很重要,请改用。默认情况下,它使用 's 进行排序,但如果要自己对元素进行排序,可以选择提供自定义类型。std::mapKeyoperator<Compare

评论

1赞 François Andrieux 8/13/2020
请注意,这也行不通,除非你能想出一个可以生成所需订单的比较器。std::map
2赞 Lukas-T 8/13/2020
@jasbindra00 如果您需要维护特定的序列,则向量或列表可能更好。
1赞 Ted Lyngmo 8/14/2020
这些匿名的反对票有时会让我感到困惑......这怎么不回答这个问题?
1赞 François Andrieux 8/14/2020
@jasbindra00 如果您计划访问元素的唯一方法是通过迭代,则地图是不可取的。当您希望以不可预测的顺序按键搜索值时,映射是可取的。
3赞 Remy Lebeau 8/14/2020
@jasbindra00这并不能真正解释为什么地图元素的顺序很重要。您可以轻松地按照地图选择使用的任何顺序从前到尾迭代地图,并按键值查找特定值。为什么需要特定顺序的密钥?请编辑您的问题,以提供您尝试解决的实际问题的示例。
3赞 François Andrieux 8/14/2020 #2

std::unordered_map 中的术语 unordered 表示顺序未指定。您不能依赖容器的顺序。所有关联容器(将值映射到键的容器)都会扰乱元素的顺序,因为这种顺序允许它们在按键搜索时获得更好的性能,这通常是使用映射的目标。unordered_*

如果您想自己控制订单,您可以使用 .您将拥有一组对,按照您想要的方式排序,但您将失去关联容器提供的快速实现。std::vector<std::pair<std::string, std::string>>find

1赞 Kenny Ostrom 8/14/2020 #3

您需要特定的任意顺序
std::unordered_map 没有可以控制
的特定顺序 std::map 根据函数对键进行排序

如果你想要像 python 的 OrderedDict 在 c++ 中这样的东西,这里有一些重复的答案: C++ 字典/映射与添加顺序 跟踪插入顺序
的 std::
map?

也许你试图变得太花哨了,而你真正需要的只是一个基本的结构对象。它只是一个变量,它的成员只是你想要的时间和方式得到的变量。

#include <vector>
#include <string>
enum elementtype_enum { NEWINTERFACE, OTHER };

struct my_element_type {
    std::string name;
    elementtype_enum type;
    std::string style_file;
    int positionx, positiony, sizex, sizey;
};

int main() { 

    std::vector<my_element_type> elements;
    my_element_type e { "IN1", NEWINTERFACE, "Style_Light.txt", 0, 0, 50, 50 };
    elements.push_back(e);
    return 0;
}