需要帮助将两个 STL 映射合并为一个(map<char,string> 和 map<string,int> into map<char,map<string,int>>)

Need help combining two STL Maps into one(map<char,string> and map<string,int> into map<char,map<string,int>>)

我正在处理一个问题,试图将我的程序转换为仅使用一个地图而不是两个单独的地图。

该程序的目标是获取一个文本文件,将文件中每个字母的所有单词存储在地图中 map<char,string>(a- 苹果八月,b-香蕉,c-柑橘椰子等),但也跟踪每个单词在带有地图的文本文件中出现的频率(苹果 2、8 月 1 日、香蕉 2 等)。最后一件事是我需要输出每个字母最常见的单词以及在另一个文本文件中出现的相应次数。

我有一个程序可以执行此操作,但我需要对其进行更新,以便不使用两个单独的地图,而是将它们全部组合成一个地图 map<char,map<string,int>>,其中 char 是字母, <string,int> pair 是以这个字母开头的单词和这个单词在文本文件中出现的次数。 我面临的最大问题是编辑使用 find() 和 insert() 函数的行。

这是我当前的代码

#include <iostream>
#include <map>
#include <string>
#include <fstream>
using namespace std;
bool onlyLetters(string s) ///function which checks if a string contains only letters of the Latin alphabet
{   bool a= true;
    for(int i=0;i<s.length();i++){
        if(!(s[i]>='a' && s[i]<='z')){
                a=false;
                break;}
        else a=true;
    }
    return a;
}
void stringLowercase(string &s) ///function which converts all letters in a word to lowercase
{
    for(int i=0;i<s.length();i++)s[i]=tolower(s[i]);
}
void insertMostCommon(char a, map<string,int> occurrences, map<string,int> &result) ///function which outputs the pairs (most common word-number of occurences) in the result map
{
    int maximum=-1;
    string maxKey; ///stores the most common word for char a
    for(map<string,int>::iterator it=occurrences.begin();it!=occurrences.end();++it) {
        if(it->second > maximum && it->first[0] == a) {
            maxKey = it->first;
            maximum = it->second;
        }
    }
    result[maxKey] = maximum; ///adds the most common word for char a and how many times it appears in the text file in the result map
}

int main()
{   typedef map<string,int> siMap; ///siMap-stringintMap
    typedef map<char,string> csMap; ///csMap- charstringMap
    ifstream fin;
    ofstream fout;
    fin.open("file.txt", ios::in);
    fout.open("output.txt", ios::out);
    csMap dictionary; ///table which will store pairs letter-word
    siMap occurrences; ///table which will store pairs word-number of occurrences
    siMap result; ///end result table which will store pairs mostCommonWordForLetter-numberOfOccurrences
    string word; ///input word
    while(fin >> word) { ///reads word from file
        stringLowercase(word); ///converts the word to lowercase
        if(onlyLetters(word)){ ///string 'word' only gets input into a table if it only contains letters
                siMap::iterator it=occurrences.find(word); ///checks if the word is already in the table
                if(it!=occurrences.end()) it->second++; ///if it is, increments the count by one
                else {
                    pair<string,int> pr(word,1); ///if it's not found, creates a new pair with value 1
                    occurrences.insert(pr);
                }
                csMap::iterator it2=dictionary.find(word[0]); ///checks if the letter is already in the table
                if(it2!=dictionary.end()) it2->second+=word+" "; ///if it is, adds the word to the list of words starting with this letter
                else {
                    pair<char,string> pr(word[0],word+" "); ///if it's not found, creates a new pair letter-word
                    dictionary.insert(pr);
                }
            }
        }

    for(csMap::iterator it2 = dictionary.begin(); it2!=dictionary.end(); ++it2) {
        cout << it2->first << " " << it2->second << endl; ///prints out the pairs letter-words that start with this letter
    }
    cout << endl;
    for(siMap::iterator it = occurrences.begin(); it!=occurrences.end(); ++it) {
        cout << it->first<< " " << it->second << endl; ///prints out the number of occurrences for each word
    }
    for(char a='a'; a<='z';a++)insertMostCommon(a,occurrences,result); ///inputs the results into the end table for each letter of the alphabet
    auto it=result.begin();
    result.erase(it); ///removes the empty pair ('' -1) at the beginning of the table
    cout << endl;
    for(auto &a: result) {
       cout << a.first << " " << a.second << endl;
       fout << a.first << " " << a.second << endl; ///word-number of occurrences
    }
    fin.close();
    fout.close();
}

这是我用于测试目的的 file.txt:

citrus apple apple leg window aa asda banana banana citrus leg tree arm leg Apple 12313 aPPle coconut

这是output.txt

apple 4
banana 2
citrus 2
leg 3
tree 1
window 1

这是控制台输出,其中还包含其他两个地图的内容:

a apple apple aa asda arm apple apple
b banana banana
c citrus citrus coconut
l leg leg leg
t tree
w window

aa 1
apple 4
arm 1
asda 1
banana 2
citrus 2
coconut 1
leg 3
tree 1
window 1

apple 4
banana 2
citrus 2
leg 3
tree 1
window 1

因此,正如所见,该程序按要求执行了所有操作,但是我无法找到一种有效的方法来将这一切转换为仅使用一个映射的程序 map<char,map<string,int>> .对于此问题的任何帮助或见解,我将不胜感激!

我发现阅读代码有点困难,因此我建议进行一些简化并在适用的情况下使用标准算法。

下面是代码中带有注释的示例:

#include <algorithm>
#include <cctype>
#include <cstdint>
#include <iostream>
#include <map>
#include <sstream>

int main() {
    std::istringstream file(
        "citrus apple apple leg window aa asda banana banana "
        "citrus leg tree arm leg Apple 12313 aPPle coconut");  

    std::map<char, std::map<std::string, std::uintmax_t>> res;
    std::string word;

    // populate the container
    while(file >> word) {

        // transform to lowercase
        std::transform(word.begin(), word.end(), word.begin(),
            [](char ch) {
                return std::tolower(ch);
            }
        );

        // add char and word if it only contains letters
        if(
          std::all_of(word.begin(), word.end(), [](char ch){return std::isalpha(ch);})
        ) {
            // res[word[0]]  Creates or returns a reference to an existing
            //               map<string,uintmax_t>.
            // [word]        Creates or uses an existing pair<string,uintmax_t> and
            //               returns a reference to the uintmax_t.
            // ++            Adds 1 to the uintmax_t
            ++res[word[0]][word];
        }
    }

    // print result in C++17 and above:
    /*
    for(const auto& [ch, scmap] : res) {
        std::cout << ch << " (words: " << scmap.size() << "):\n";
        for(const auto& [word, count] : scmap) {
            std::cout << ' ' << count << ' ' << word << '\n';
        }
    }
    */

    // print result in C++11 or C++14:
    for(const auto& ch_scmap : res) {
        char ch = ch_scmap.first;
        auto& scmap = ch_scmap.second;
        std::cout << ch << " (words: " << scmap.size() << "):\n";
        for(const auto& word_count : scmap) {
            const auto& word = word_count.first;
            auto& count = word_count.second;
            std::cout << ' ' << count << ' ' << word << '\n';
        }
    }
}

Demo