【问题标题】:how to iterate through a set of sets C++如何遍历一组集合 C++
【发布时间】:2015-01-26 14:51:12
【问题描述】:

对 C++ 很陌生,仅一周左右,我想遍历一组嵌套集合并将内部集合中的每个元素写入文件中的一行。 每个内部集都有 3 个元素,我希望所有三个元素都在同一行。 我的设置如下:

   // Define "bigSet" and initiate as empty set "Triplets"
   typedef set < set<string> > bigSet;
   bigSet Triplets;

我尝试过这样的事情来解决它,但它给了我一个错误......

    // Iterate through and print output
    set <string>::iterator it;
    for(it = Triplets.begin(); it != Triplets.end(); it++){
        cout << *it << endl;
    }

非常感谢任何帮助,谢谢!

【问题讨论】:

  • bigSet 的每个元素都是 set,因此您需要以与遍历 bigSet 大致相同的方式遍历每个元素。
  • 为了将来参考,请始终包含您收到的确切错误消息。

标签: c++ iterator set nested-sets


【解决方案1】:

我会这样做:

 // Iterate through and print output
    set < set <string> >::iterator it_ex; // iterator for the "outer" structure
    set <string>::iterator it_in; // iterator for the "inner" structure

    for(it_ex = Triplets.begin(); it_ex != Triplets.end(); it_ex++)
    {
        for(it_in = it_ex->begin(); it_in != it_ex->end(); it_in++)   
            cout << *it_in << ", ";
        cout << endl;
    }

【讨论】:

  • 为什么要在for之前声明迭代器?这是非常单调的。 (在for 中声明迭代器是适合auto 的地方,如果你有C++11。事实上,我认为这就是为什么auto 被添加到语言中的原因。)
  • 同意,这样写是为了提高可读性和更好地理解新手。 auto 很棒,但除非您确切知道自己在做什么,否则不适合使用。
【解决方案2】:

三胞胎不是set&lt;string&gt;;这是一个set&lt;set&lt;string&gt;&gt;; Triplets 中的每个项目本身都是一个set,而不是可以包含多个字符串。

迭代器必须与容器的类型相匹配;使用两级嵌套容器,您应该迭代两次:

set<set<string>>::iterator it;
set<string>::iterator it2;
for(it = Triplets.begin(); it != Triplets.end(); it++) {
    for (it2 = it->begin(); it2 != it->end(); ++it2) {
        cout << *it2 << endl;
    }
}

【讨论】:

  • @NeilKirk 确实;编辑了我的答案以使其更清晰
【解决方案3】:

Tripletsset &lt; set&lt;string&gt; &gt; 类型,因此需要set &lt; set&lt;string&gt; &gt;::iteratorbigSet::iterator 类型的迭代器。它不是类型set &lt;string&gt;。你也可以使用const_iterator

请注意,迭代 Triplets 会为您提供指向另一个集合的迭代器,而不是字符串。

同时考虑

for (const auto& i : Triplets)
{
    for (const auto& j : i)
    {
        cout << j << endl;
    }
}

【讨论】:

    【解决方案4】:

    您有一个错误,因为Triplets.begin() 不是set&lt;string&gt;::iterator 类型,而是set&lt;set&lt;string&gt;&gt;::iterator

    您需要做的是有两个循环:一个用于迭代外部集合,另一个用于内部集合。

    set<set<string>>::iterator it;
    for(it = Triplets.begin(); it != Triplets.end(); ++it)
    {
        set<string>::iterator it2;
        for(it2 = it->begin(); it2 != it->end(); ++it2)
        {
            cout << *it2;
        }
    
        cout << endl;
    }
    

    如果您在迭代器上使用递增/递减运算符 (++/--),最好使用前缀版本 (++it) 而不是后缀版本 (it++)。这是因为后缀会在迭代器递增之前创建一个副本(然后返回该副本),但在这种情况下,您不需要它。

    此外,如果您使用的是 C++11,则可以使用基于范围的 for 循环和 auto 关键字,这大大简化了事情:

    for(const auto &innerSet : Triplets)
    {
        for(const auto &innerSetElement : innerSet)
        {
            cout << innerSetElement;
        }
    
        cout << endl;
    }
    

    【讨论】:

    • 好多了,但我不会在基于for 的范围内使用auto。对于经典迭代器以外的任何东西,不拼出类型是混淆的。
    • 是的,但这取决于代码,如果您正确命名它会很好。在这里,我将引用命名为这样,以便 OP 更容易理解隐藏在那里的内容,但仍显示 auto
    【解决方案5】:

    首先:如果他们是三胞胎,你确定std::set 是你的类型吗? 想要内在价值。也许class 会更多 适当的,在这种情况下,你为`class定义一个operator&lt;&lt;, 你的简单循环完美地工作。比如:

    class Triplet
    {
        std::string x;
        std::string y;
        std::string z;
    public:
        //  Constructors to enforce that none of the entries are identical...
        //  Accessors, etc.
        friend std::ostream& operator<<( std::ostream& dest, Triplet )
        {
            dest << x << ", " << y << ", " << z;
            return dest;
        }
    };
    

    然后输出:

    for ( Triplet const& elem : Triplets ) {
        std::cout << elem << std::endl;
    }
    

    否则:您需要为输出定义所需的格式。在 特别是,您可能需要在 线,例如。这意味着您可能无法使用基于范围的 for,至少不是内循环。你需要类似的东西:

    for ( std::set<std::string> const& triplet : Triplets ) {
        for ( auto it = triplet.cbegin(); it != triplet.cend(); ++it ) {
            if ( it != triplet.cebegin() ) {
                std::cout << ", ";
            }
            std::cout << *it;
        }
        std::cout << std::endl;
    }
    

    (如果三元组的集合很大,你肯定要考虑 将std::endl 替换为'\n'。但是当然,如​​果真的 很大,你可能不会输出到std::cout。)

    【讨论】:

      猜你喜欢
      • 2019-12-04
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 2014-07-21
      • 2014-04-11
      • 2018-11-17
      • 1970-01-01
      相关资源
      最近更新 更多