C ++ STL映射,我不希望它排序!

问题描述 投票:23回答:19

这是我的代码

map<string,int> persons;

persons["B"] = 123;
persons["A"] = 321;


for(map<string,int>::iterator i = persons.begin();
    i!=persons.end();
    ++i)
{
    cout<< (*i).first << ":"<<(*i).second<<endl;
}

预期输出:

  B:123
  A:321

但是它给出的输出是:

  A:321
  B:123

我希望它保持在map<string,int>中插入键和值的顺序。

有可能吗?还是应该使用其他STL数据结构?哪一个?

c++ stl
19个回答
37
投票

没有标准容器可以直接执行您想要的操作。如果要保持插入顺序,显然可以使用的容器是矢量。如果您还需要按字符串查找,请使用矢量和地图。该映射通常是从字符串到向量的索引,但是由于您的数据已经是整数,因此您可能只想复制它,具体取决于您的用例。


0
投票

我也认为Map并非可行之路。 Map中的键构成一个Set;单个密钥只能出现一次。在插入映射期间,映射必须搜索键,以确保它不存在或更新该键的值。为此,重要的是(在性能方面)键以及条目具有某种排序。因此,具有插入顺序的Map在插入和检索条目时效率非常低。


0
投票

是,地图容器不适合您。按照您的要求,您需要以下代码:


0
投票

我将投票给typedef std::vector< std::pair< std::string, int > > UnsortedMap;


0
投票

Map是有序集合(模板中的第二个参数是订单函子),已设置。如果要按顺序弹出该序列中的元素,则应使用双端队列或列表或向量。


0
投票

为了执行任务并高效地进行操作,地图使用哈希表和排序。因此,如果您愿意放弃插入顺序的存储以获取按键查找的便利和性能,则可以使用地图。


0
投票

在插入Map时,将Map与迭代器向量一起使用。 (保证地图迭代器不会失效)


0
投票

``结构比较:public binary_function {bool operator()(int a,int b){返回true;}};


0
投票

代替地图,您可以将pair函数与向量一起使用!例如:


0
投票

std::unordered_map您可以签出。从第一个角度看,它似乎可以解决您的问题。


0
投票

如果您不想使用Boost :: multi_index,我将概念证明类模板放在此处进行审查:


20
投票

[就像Matthieu在另一个答案中所说,Boost.MultiIndex library似乎是您想要的正确选择。但是,此库在一开始使用起来可能会有些困难,特别是如果您没有太多C ++经验的话。这是您使用库来解决问题代码中确切问题的方法:

struct person {
    std::string name;
    int id;
    person(std::string const & name, int id) 
    : name(name), id(id) { 
    }
};

int main() {

    using namespace::boost::multi_index;
    using namespace std;

    // define a multi_index_container with a list-like index and an ordered index
    typedef multi_index_container<
      person,        // The type of the elements stored
      indexed_by<    // The indices that our container will support
        sequenced<>,                           // list-like index
        ordered_unique<member<person, string, 
                              &person::name> > // map-like index (sorted by name)
      >
    > person_container;

    // Create our container and add some people
    person_container persons;
    persons.push_back(person("B", 123));
    persons.push_back(person("C", 224));
    persons.push_back(person("A", 321));

    // Typedefs for the sequence index and the ordered index
    enum { Seq, Ord };
    typedef person_container::nth_index<Seq>::type persons_seq_index;
    typedef person_container::nth_index<Ord>::type persons_ord_index;

    // Let's test the sequence index
    persons_seq_index & seq_index = persons.get<Seq>();
    for(persons_seq_index::iterator it = seq_index.begin(), 
                                    e = seq_index.end(); it != e; ++it)
        cout << it->name << ":"<< it->id << endl;
    cout << "\n";

    // And now the ordered index
    persons_ord_index & ord_index = persons.get<Ord>();
    for(persons_ord_index::iterator it = ord_index.begin(), 
                                    e = ord_index.end(); it != e; ++it)
        cout << it->name << ":"<< it->id << endl;
    cout << "\n";

    // Thanks to the ordered index we have fast lookup by name:
    std::cout << "The id of B is: " << ord_index.find("B")->id << "\n";
}

将产生以下输出:

B:123
C:224
A:321

A:321
B:123
C:224

The id of B is: 123

9
投票

地图绝对不适合您:

“在内部,按照在构造上设置的特定严格的弱排序标准,将图中的元素从低到高的键值进行排序。”

here中摘录。

不幸的是,STL中没有无序的关联容器,因此您可以使用vector之类的非关联容器,也可以编写自己的:-(


4
投票

除了Neil建议使用向量+映射组合之外,如果您既需要保持插入顺序又需要按键搜索的能力,还可以考虑使用boost多索引库,该库提供了以多种方式寻址的容器。] >


4
投票

映射和集合旨在对数据施加严格的弱排序。斯特里克弱排序可确保没有条目为equavalent(不同于相等)。


3
投票

我偶尔会遇到相同的问题,这是我的解决方案:https://github.com/nlohmann/fifo_map。它是仅标头的C ++ 11解决方案,可以用作std::map的直接替代。


2
投票

嗯,没有STL容器可以真正满足您的要求,但是有可能。


1
投票

使用向量。它使您可以完全控制订购。


1
投票

为了保留所有时间复杂性约束,您需要map + list:

© www.soinside.com 2019 - 2024. All rights reserved.