【问题标题】:Composite map: take data from another Map复合地图:从另一个地图中获取数据
【发布时间】:2019-01-24 11:07:44
【问题描述】:

我需要使用map&lt;string,int&gt;从文件中取出出现的单词,然后我需要将它们复制到map<int, vector<string>, cmpDec >,并按降序打印。

我尝试将文件中的词频提取到map&lt;string, int&gt;,然后尝试将其复制到map<int, vector<string> >,但没有结果

我已经声明了 2 张地图:

map<string, int> text;
map<int, vector<string>, cmpDec> freq;

我从第一个地图中的文件中获取带有单词频率的文本:

while (rf >> words) {
    text[words]++;
}

现在我必须将频率放在第二张地图中(必需),其中我需要第一个 int,用于单词频率的数量,vector 与每个频率的单词,以及降低频率的比较. 现在我正在尝试通过以下方式将数据从第一张地图中放入第二张地图中:

map<string, int>::iterator iter_map1 = text.begin();
map<int, vector<string>>::iterator iter = freq.begin();
vector<string>::iterator iter_v;
for (; iter_map1 != text.end(); ++iter_map1) {
   iter->first.insert(make_pair(iter_map1->second, iter->second.push_back(iter_map1->first)));
}

它在 iter->second.... 行给出 2 个错误:

...\BagOfWords.cpp|56|error: request for member 'insert' in 'iter.std::_Rb_tree_iterator<_Tp>::operator-><std::pair<const int, std::vector<std::__cxx11::basic_string<char> > > >()->std::pair<const int, std::vector<std::__cxx11::basic_string<char> > >::first', which is of non-class type 'const int'|

...\BagOfWords.cpp|56|错误:无效表达式的使用|

我做错了什么?有没有更简单的方法可以从文件中获取单词(及其频率)并将它们放在第二张地图上,而无需从第一张地图中传递?

【问题讨论】:

  • 使用freq[cnt] 插入它们有什么问题?

标签: c++ dictionary vector stl


【解决方案1】:

使用C++17,您可以执行structured binding,这在迭代map 时很有帮助。

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

using WordCounts       = std::map<std::string, int>;
using FrequencyOfWords = std::map<int, std::vector<std::string>, std::greater<int>>;

int main()
{
    WordCounts word_counts;
    FrequencyOfWords words_freq;
    std::vector<std::string> words = {"test", "hello", "test", "hello", "word"};

    for(const auto& word : words)
        word_counts[word]++;

    for(const auto& [word, count] : word_counts)
        words_freq[count].push_back(word);

    for (const auto& [freq, words] : words_freq)
    {
        std::cout << "freq " << freq << " words";
        for (auto const& word: words)
            std::cout << " " << word;
        std::cout << '\n';
    }
}

【讨论】:

    【解决方案2】:

    我不认为您可以一次性完成此操作,因为您不知道预先计算字数。

    首先,有几点建议。使用 typedef(或 using 用于 C++ 11 或更高版本)。这将为您节省一些输入,并确保您的类型正确。在您的代码中,freqiter 没有相同的底层容器类型(它们在使用的比较方面有所不同)。

    其次,尽量使用标准库。您没有显示cmpDec,但我猜它是基于大于而不是默认小于的比较器。我更愿意看到 std::greater&lt;int&gt; 而不是自定义比较器。

    对于你的错误,在一行中

    iter->first.insert(...
    

    iter 位于freq 的开头,您正尝试插入first,即int

    应该是这样的

    freq[iter_map1->second].push_back(iter_map1->first);
    

    打破它

    • freq[iter_map1-&gt;second] 这使用来自textint 字数来查找freq 中的条目。如果没有条目,则会在freq 中插入一个空条目。
    • .push_back(iter_map1-&gt;first) 这会将stringtext 插入到在上一步中找到或创建的vector

    这是我认为您正在努力实现的目标的完整示例。

    #include <map>
    #include <vector>
    #include <string>
    #include <functional>
    #include <fstream>
    #include <iostream>
    
    using std::map;
    using std::vector;
    using std::string;
    using std::greater;
    using std::ifstream;
    using std::cout;
    
    using WordCounts = map<string, int>;
    using FrequencyOfWords = map<int, vector<string>, greater<int>>;
    
    int main()
    {
        WordCounts text;
        FrequencyOfWords freq;
    
        ifstream rf("so26.cpp");
    
        string words;
        while (rf >> words)
        {
            text[words]++;
        }
    
        WordCounts::const_iterator iter_map1 = text.begin();
        for (; iter_map1 != text.end(); ++iter_map1)
        {
            freq[iter_map1->second].push_back(iter_map1->first);
        }
    
        for (auto const& e: freq)
        {
            cout << "freq " << e.first << " words";
            for (auto const& w: e.second)
            {
                cout << " " << w;
            }
            cout << "\n";
        }
    }
    

    【讨论】:

    • 我试过这样,但编译器给出错误“与运算符[]不匹配”
    • 更好的是,不要使用typedefusing,而是使用auto。例如auto iter_map1 = text.begin();.
    • 您声明了变量iter_v,但您从未使用它。
    • 我已经删除了 iter_v(它来自 OP 的代码)。我想说明关于 typedef/auto 的观点,否则我会推荐 auto。
    【解决方案3】:

    也许我误解了这个问题,但我认为以下是你想要的(我更喜欢无序的地图,因为它们更快而且你似乎不需要排序)

    std::unordered_map<std::string,int> word_counts;
    std::string word;
    while(input >> word)
        word_counts[word]++;
    
    std::unordered_map<int,std::vector<std::string>> words_by_freq;
    for(const auto& counted : word_counts)
        words_by_freq[counted::second].push_back(counted::first);
    

    【讨论】:

      猜你喜欢
      • 2021-01-06
      • 1970-01-01
      • 1970-01-01
      • 2015-09-05
      • 2020-08-29
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      相关资源
      最近更新 更多