C ++:将map <string,int =“”> push_back转换为vector <map <string,int =“”>&gt;通过迭代器?</map <string,> </string,>

时间:2012-01-24 23:28:57

标签: c++ map iterator g++ push-back

我目前正在学习加速C ++(Koenig / Moo)这本书,我在其中一个练习中遇到了麻烦。问题是编写一个程序,它将一些单词序列作为输入,然后将它存储在地图中。字符串是输入的单词,关联的int是每个单词出现的次数。然后,您必须按其出现的次数对单词进行排序;也就是说,通过价值而不是关键。您无法按值对地图进行排序,因此我尝试将元素复制到矢量中,我打算使用谓词进行排序。不幸的是,我得到的是一个充满g ++错误的屏幕。它们似乎来自同一个地方 - 将我的地图元素放入我的矢量中,我尝试这样做:

int main()
{
    map<string, int> counters;

    cout << "Enter some words followed by end-of-file (ctrl-d): ";
    string word;
    while (cin >> word)
       ++counters[word];

    //maps cannot be sorted by values, so pass the elements of counters to a vector
    vector<map<string, int> > vec_counters;

    map<string, int>::const_iterator it = counters.begin();
    while (it != counters.end()) {
       vec_counters.push_back(*it);
       ++it;
    }

这显然只是第一部分,但我甚至无法编译。我收到错误:

32:31:错误:没有匹配函数来调用std :: vector,int&gt; &gt; :: push_back(const std :: pair,int&gt;&amp;)' /usr/include/c++/4.5/bits/stl_vector.h:741:7:注意:候选者是:void std :: vector&lt; _Tp,_Alloc&gt; :: push_back(const value_type&amp;)[with _Tp = std :: map ,int&gt;,_ Alloc = std :: allocator,int&gt; &gt;,value_type = std :: map,int&gt;]

我想我做的事情从根本上说是愚蠢的...但我不能为我的生活看到什么......

任何帮助都会很棒!

C

4 个答案:

答案 0 :(得分:4)

我很确定你不是在寻找地图矢量:

#include <map>
#include <vector>
#include <string>
#include <iostream>

using namespace std;
int main()
{
    map<string, int> counters;

    cout << "Enter some words followed by end-of-file (ctrl-d): ";
    string word;
    while (cin >> word)
       ++counters[word];

    vector<std::pair<string, int> > vec(counters.begin(), counters.end());
}

答案 1 :(得分:2)

有点偏离主题,但这是一个使用bimap的性感解决方案,这是一个双方都作为键的地图。

#include <iostream>
#include <sstream>
#include <string>
#include <boost/bimap.hpp>
#include <boost/bimap/list_of.hpp>
#include <boost/bimap/set_of.hpp>

int main()
{
    boost::bimap<boost::bimaps::set_of<std::string>, boost::bimaps::list_of<int>> m;

    for (std::string line; std::getline(std::cin, line); )
    {
        ++m.left[line];
    }

    auto & bml = m.left;
    auto & bmr = m.right;

    bmr.sort();

    for (auto const & p : bml) { std::cout << p.first << " => " << p.second << "\n"; }
    for (auto const & p : bmr) { std::cout << p.first << " => " << p.second << "\n"; }
}

答案 2 :(得分:0)

取消引用std::map<std::string, int>::const_iterator会为您提供std::pair<std:string, int>,而不是std::map<std::string, int>,所以代替此:

vector<map<string, int> > vec_counters;

你想要这个:

vector<std::pair<string, int> > vec_counters;

答案 3 :(得分:0)

如果要在插入地图项后对向量进行排序,则也可以使用std::set。集合中的元素总是被排序。如果您想在以后插入新元素,这将特别有用。但是,由于要按值对地图条目进行排序,因此必须将翻转的键值对存储到集合中。为了清楚起见,我省略了以下C ++ 11代码中的输入内容:

int main() {
    std::map<std::string, int> counters{
        {"sorted", 2}, {"value" , 5}, {"is" , 2}, {"by" , 3}, {"this" , 1}
    };

    std::set<std::pair<int, std::string>> s;  // Use a set instead of a vector.

    for (auto const &kv : counters)
        s.emplace(kv.second, kv.first);  // Flip the pairs.

    for (auto const &vk : s)
        std::cout << vk.second << ": " << vk.first << std::endl;

    return 0;
}

输出:

  

此:1
  是:2
  排序:2
  创建人:3
  值:5

如果要按降序排序,则可以如下定义集合:

using flippedPair = std::pair<int, std::string>;
std::set<flippedPair, std::greater<flippedPair>> s;

Shorter C++17 code on Coliru