4

我目前正在学习Accelerated 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<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::map, int>, _Alloc = std::allocator, int> >, value_type = std::map, 整数>]

我究竟做错了什么?

4

5 回答 5

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());
}
于 2012-01-24T23:34:33.860 回答
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"; }
}
于 2012-01-25T00:02:09.857 回答
1

你想把地图的元素放在一个向量中。地图是成对的,而不是其他地图。因此,您的向量应该是成对的向量。

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

于 2012-01-24T23:39:10.033 回答
0

取消引用 astd::map<std::string, int>::const_iterator给你 a std::pair<std:string, int>,而不是 a std::map<std::string, int>,所以不是这个:

vector<map<string, int> > vec_counters;

你要这个:

vector<std::pair<string, int> > vec_counters;
于 2012-01-24T23:32:24.007 回答
0

如果您想在插入地图条目后对矢量进行排序,那么您也可以使用 astd::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 代码

于 2019-09-16T09:14:26.717 回答