【问题标题】:How can I print the content of a map containing a set?如何打印包含集合的地图内容?
【发布时间】:2012-12-04 13:20:41
【问题描述】:

我的地图声明如下:

map < string, set<string> > index;
std::map < string, set<string> >::iterator iter;

我想打印index 的内容。因此,我写了以下内容:

for (iter = index.begin(); iter!= index.end(); iter++){
    cout << iter->first << endl;}  // It's OK.

但是如果我尝试打印iter-&gt;second,上面的代码不起作用:

for (iter = index.begin(); iter!= index.end(); iter++){
    cout << iter-> second << endl;}  // Doesn't work.

我想这是因为index 中的second 是一组字符串而不是简单的字符串。但是我怎样才能打印出来呢?

【问题讨论】:

  • 您可能正在寻找std::multimap&lt;string, string&gt;

标签: c++ dictionary set output stdmap


【解决方案1】:

如果你想打印

iter->second

使用操作符second 表示的字符串集合:

set<string>::iterator iterator_;

更新[迭代器]

迭代很容易,忍者解决方案是重载运算符! :P

迭代:

map<string, set<string> >::iterator iter_;
for (iter_ = index_.begin(); iter_ != index_.end(); iter_++) {
cout << iter_->first << " - ";
    set<string>::iterator iterator_;
for (iterator_ = s.begin(); iterator_ != s.end(); iterator_++) {
    cout << *iterator_ << " - ";
}   
    cout << endl;
}

更新[重载ostream&操作符
class MySet: public set<string> {
friend ostream& operator<<(ostream& out, const MySet& s) {
    set<string>::iterator iterator_;
    for (iterator_ = s.begin(); iterator_ != s.end(); iterator_++) {
        out << *iterator_;
    }
    return out;
}

void test() {
    map<string, MySet> index_;
    map<string, MySet>::iterator iter_;
    for (iter_ = index_.begin(); iter_ != index_.end(); iter_++) {
        cout << iter_->first << " - ";
        cout << iter_->second;  
    }
}
};

【讨论】:

  • 感谢您的回答。我尝试仅使用您的建议进行迭代。
  • 你试过了吗?我也发布了第二种方法!
  • 请记住,这个operator&lt;&lt; 只能从它自己的命名空间中找到,而所有其他operator&lt;&lt; 可以通过依赖于参数的查找从任何命名空间中找到。 ADL 仅将 namespace std 添加到搜索中。
【解决方案2】:

在过去的几年里,我一直在使用以下功能。如果重载运算符 之间进行选择

随着 C++11 引入 lambda 和基于范围的 for 循环,我可能不需要它的频率。

#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>

using namespace std;

template<typename C>
void print_container(ostream& os, const C& c)
{
  copy(c.begin(), c.end(), ostream_iterator<int>(os, " "));
}

int main(void)
{
  vector<int> v; 
  v.push_back(1); 
  v.push_back(2);
  v.push_back(3);

  print_container(v);
}

【讨论】:

    【解决方案3】:

    (在我看来)C++ 中最烦人的事情是没有为标准库类型定义输出运算符。

    你需要一些代码有点像:

    typedef std::map < string, set<string> >::iterator iter;
    
    for (iter = index.begin(); iter!= index.end(); iter++) {
      std::cout << iter->first << " : {";
      for(set<string>::iterator it = iter->second.begin(); it != iter->second.end(); ++it) {
        std::cout << *it << " ";
      }
      std::cout << "}\n";
    }
    

    【讨论】:

      【解决方案4】:

      正如您所说,iter-&gt;second 代表您代码中的一组字符串。您不能简单地打印它,因为输出流的operator&lt;&lt; 默认不知道如何格式化std::set。正如 Luca Davanzo 的 answer 中所述,一种解决方案是为您的集合重载该运算符。

      另一个解决方案,如 Chris Jefferson 的 answer 所示,是简单地添加另一个循环来迭代您的集合。但是,可以通过使用以下C++11 功能来提高该解决方案的可读性:range-based for loops 和占位符auto。因此,您的代码可能如下所示:

      std::map<std::string, std::set<std::string>> index;
      index["a"] = { "v", "w" };
      index["b"] = { "x", "y", "z" };
      
      for (const auto &mapItem : index) {
          std::cout << "m[" << mapItem.first << "] =";
          for (const auto &setItem : mapItem.second)
              std::cout << " " << setItem;
          std::cout << std::endl;
      }
      

      输出:

      m[a] = v w
      m[b] = x y z

      由于C++17,您可以将基于范围的for循环与structured bindings一起使用。这进一步提高了可读性,因为您可以从代码中删除 firstsecond 成员:

      for (const auto &[k, v] : index) {
          std::cout << "m[" << k << "] =";
          for (const auto &s : v)
              std::cout << " " << s;
          std::cout << std::endl;
      }
      

      Code on Coliru

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-25
        • 2019-01-04
        • 2016-03-19
        • 2018-10-07
        • 2016-01-02
        • 1970-01-01
        相关资源
        最近更新 更多