Составная карта: взять данные с другой карты - PullRequest
0 голосов
/ 24 января 2019

Мне нужно взять вхождения слов, взятых из файла, используя 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;

Iвзять текст из файла на первой карте со словом частоты:

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

Теперь я должен поместить частоты на второй карте (обязательно), где мне нужно иметь первую int, дляnum частот слов, 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)));
}

Это дает 2 ошибки в строке iter-> second ....:

...\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 | ошибка: неверное использование пустого выражения |

Что я делаю не так?Есть ли более простой способ взять слова (и их частоты) из файла и поместить их на вторую карту, не переходя от первой?

Ответы [ 3 ]

0 голосов
/ 24 января 2019

Возможно, я неправильно понял вопрос, но я считаю, что следующее делает то, что вы хотите (я предпочитаю неупорядоченные карты, так как они быстрее и вам не нужно упорядочивать)

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);
0 голосов
/ 25 января 2019

С 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';
    }
}
0 голосов
/ 24 января 2019

Я не думаю, что вы можете сделать это за один проход, так как не знаете, что слово считается заранее.

Сначала пара рекомендаций.Используйте typedef (или using для C ++ 11 или новее).Это избавит вас от необходимости печатать, а также обеспечит правильность ваших типов.В вашем коде freq и iter нет одного и того же базового типа контейнера (они отличаются в используемом сравнении).

Во-вторых, постарайтесь максимально использовать стандартную библиотеку.Вы не показываете cmpDec, но я предполагаю, что это компаратор, основанный на значении «больше, чем», а не на значении «по умолчанию».Я предпочел бы видеть std::greater<int>, а не пользовательский компаратор.

Для ваших ошибок в строке

iter->first.insert(...

iter находится в начале freq, и выпытаясь вставить в first, что является int.

Вероятно, это должно быть что-то вроде

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

Сломать это

  • freq[iter_map1->second] При поиске используется число слов int из textзапись в freq.Если запись отсутствует, пустая будет вставлена ​​в freq.
  • .push_back(iter_map1->first). Вставка string из text в 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";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...