如何通过迭代器将 map<string, int> push_back 到 vector<map<string, int>>?

How can I push_back a map<string, int> into a vector<map<string, int>> via an iterator?

本文关键字:gt lt int string map back vector push 迭代器 何通过      更新时间:2023-10-16

我目前正在学习《加速C++》一书(Koening/Moo),其中一个练习有问题。任务是编写一个程序,将某个单词序列作为输入,然后将其存储在map<string, int>中。字符串是输入的单词,相关的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>>::push_back(const std::pair,int>&)'/usr/include/c++/4.5/bits/stl_vector.h:741:7:注意:候选者是:void std::vector&lt_Tp,_Alloc>::push_back(const value_type&)[带_Tp=std::map,int>,_Alloc=std::分配器,int>>,value_type=std::映射,int>]

我做错了什么?

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

#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());
}

有点离题,但这里有一个使用bimap的性感解决方案,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"; }
}

您想要将映射的元素放在向量中。地图是由成对的地图组成的,而不是其他地图。因此,你的向量应该是成对的向量。

也就是说,看起来你首先想要向量的原因是按照地图中的值排序。为什么不把你的地图改为map< int, string >呢?这将导致它按int升序排序:映射中的元素按照特定的严格弱排序标准从低到高的键值进行排序。

取消引用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;

如果您想在插入映射条目后对向量进行排序,那么您也可以使用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;

Coliru 上较短的C++17代码