【问题标题】:How can I print the content of map<string, map<int, int>> to cout?如何将 map<string, map<int, int>> 的内容打印到 cout?
【发布时间】:2023-03-17 15:47:01
【问题描述】:

如何打印嵌套地图的内容?我正在计算一个单词在文件中出现的次数,按行号和每行的次数报告它。单词、行和每行出现的次数存储在以下容器中:

map<string, map<int, int>> tokens;

但是,我不确定语法。我正在使用以下代码打印列出所有单词的外部地图,但无法弄清楚如何打印内部值(行号和单词在每行上出现的次数)。我假设我可以将它内联在 for 循环中,但我不知道如何:

for (map <string, map<int, int>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
    cout << it->first << " : " << /* assume I can include another statement here to print the values? */ endl;
}

我正在尝试获得与此类似的输出:

(单词:行:出现次数,行:出现次数,...)

about : 16:1, 29:1, 166:1, 190:1, 191:1
above : 137:1
accompanied : 6:1
across : 26:1
admit : 20:1
advancing : 170:1
.
.
.

【问题讨论】:

  • 在循环内部,执行map&lt;int, int&gt; const &amp;the_map = it-&gt;second;,然后像对tokens 那样遍历the_map
  • 迭代内部有什么问题?
  • 顺便说一句,使用const_iterator 而不是iterator
  • 在编辑中,t-&gt;second 应该是it-&gt;second
  • 请不要在问题中添加所选答案中可用的解决方案。这只是不必要的重复,一旦其中一个更新而不为另一个更新,就会不同步。

标签: c++ string dictionary iterator output


【解决方案1】:

其实很简单。

您只需使用它获取内部映射->第二个,然后以相同的方式迭代。

因此,你会这样写:

for (map <string, map<int, int>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
    cout << it->first << " : ";
    map<int, int> &internal_map = it->second;
    for (map<int, int>::iterator it2 = internal_map.begin(); it2 != internal_map.end(); ++it2){
        if (it2 != internal_map.begin())
            cout << ",";
        cout << it2->first << ":" << it2->second;
    }
    cout << endl;
}

如果你有 C++11 支持,你可以写这样的东西:

for (auto it : tokens) {
    cout << it->first << " : ";
    map<int, int> &internal_map = it->second;
    for (auto it2: internal_map) {
        if (it2 != internal_map.begin())
            cout << ",";
        cout << it2->first << ":" << it2->second;
    }
    cout << endl;
}

【讨论】:

  • 这在 C++11 中会更加优雅:)
  • @MattMcNabb:C++11 并非随处可用,但无论哪种方式都提供了解决方案。
  • 绝对喜欢自动版本,但也很高兴看到类型,因为我不太了解迭代器并且正在努力改进它们。尝试执行此操作时,我在 it2->second 之前的流输出运算符上出现错误,说“没有运算符
  • 我弄错了“->”而不是“.”不过,对于自动版本。在获得更多反馈后,我会稍后修复它,因为它现在已经被编辑了好几次。逗号后面也少了一个空格。 :)
  • 如果没有错别字等,我无法想象会发生这种情况。
【解决方案2】:

由于我们只打印元素,而不是修改它,我会更多地使用const、(a)const 参考和(b)const iterators。

此外,对于 C++11 之前的版本,它有助于为复杂类型定义 typedef

#include <string>
#include <map>
#include <iostream>
using namespace std;

typedef map<int, int> InnerMap;
typedef map<string, InnerMap> OuterMap;

void printClassic( OuterMap const & tokens ) {

    for( OuterMap::const_iterator cit = tokens.begin();
             cit != tokens.end(); ++cit ) {
        cout << cit->first << " : ";
        InnerMap const & imap = cit->second;
        for( InnerMap::const_iterator cit2 = imap.begin(); 
                 cit2 != imap.end(); ++cit2 ) {
        cout << cit2->first << ":" << cit2->second << ",";
        }
        cout << endl;
    }
}

void printCpp11( OuterMap const & tokens ) {
    for( auto const & cit : tokens ) {
        cout << cit.first << " : ";
        auto const & imap = cit.second;
        for( auto const & cit2 : imap ) {
            cout << cit2.first << ":" << cit2.second << ",";
        }
        cout << endl;
    }
}

【讨论】:

    【解决方案3】:

    C++17

    由于C++17,您可以使用range-based for loopsstructured bindings 来迭代地图。 这样lpapp's C++11 solution的可读性可以进一步提高如下:

    for (auto const &[k1, v1] : tokens) {
        std::cout << k1 << " : ";
        for (auto const &[k2, v2] : v1) {
            if (&k2 != &v1.begin()->first)
                std::cout << ", ";
            std::cout << k2 << ":" << v2;
        }
        std::cout << std::endl;
    }
    

    注意:我承认,打印逗号的检查有点混乱。如果您正在寻找更好的解决方案,您 可能想看看this Q&A

    Code on Coliru

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      相关资源
      最近更新 更多