合成地图:从另一个地图获取数据

Composite map: take data from another Map

本文关键字:地图 获取 数据 另一个      更新时间:2023-10-16

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

我试着把一个文件中的单词频率复制到map<string, int>,然后我试着将它复制到一个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->秒上给出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|错误:无效使用void表达式|

我做错了什么?有没有一种更简单的方法可以从文件中提取单词(及其频率),并将其放在第二张地图上,而不必从第一张地图上经过?

使用C++17,您可以执行结构化绑定,这在迭代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';
}
}

我不认为你可以一次完成这项工作,因为你不知道单词的开头数。

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

其次,尽量使用标准库。您没有显示cmpDec,但我猜它是一个基于大于而不是默认小于的比较器。我更喜欢看std::greater<int>,而不是自定义比较器。

对于您的错误,在行

iter->first.insert(...

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

这应该是类似的东西

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

分解

  • freq[iter_map1->second]这使用来自textint字计数来查找freq中的条目。如果没有条目,则将向freq插入一个空条目
  • .push_back(iter_map1->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";
}
}

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

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);