【问题标题】:How to iterate map<int, vector <int>>? [duplicate]如何迭代 map<int,vector <int>>? [复制]
【发布时间】:2021-12-31 08:53:33
【问题描述】:

我有 map 像这样:

#include <iostream>
#include <map>
#include <vector>

using namespace std;

int main() {
    
    map<int, vector <int>> someMap;
    someMap[5] = {5, 2, 3, 7};
    someMap[151] = {5, 9, 20};

    return 0;
}

我需要找到每个地图值中的最后一个向量元素。输出必须是这样的:

7
20

谢谢:)

【问题讨论】:

  • 像大多数容器一样,std::map 有一个 reverse_iterator。文档位于 cppreference dot com。 map::rbegin( ) 将是一个开始寻找的好地方。
  • for (auto&amp; vector : someMap) { ... }。事实上,您甚至没有努力查找标准容器的基本功能,或者至少忽略了在您的问题中显示该尝试使您的问题有被关闭的危险。请阅读How to Ask 以及如何制作minimal reproducible example。展示您尝试过的内容以及您尝试的无效内容。
  • @super 应该是for (auto&amp; [integer, vector] : someMap) { ... }。如果你只做for (auto&amp; vector : someMap)vector 将不包含向量,而是一个std::pair&lt;int, vector&lt;int&gt;&gt;

标签: c++ iterator stdvector stdmap


【解决方案1】:

你必须爱上 C++17 structured bindings

std::map<int, std::vector<int>> m = {
    {5, {5, 2, 3, 7}},
    {151, {5, 9, 20}},
};

for (const auto& [_, v] : m)
{
    if (!v.empty())
    {
        int last = v.back();
    }
}

其他一些资源:

【讨论】:

    【解决方案2】:

    可以使用std::vector::back成员函数如下图:

    #include <iostream>
    #include <map>
    #include <vector>
    #include <cassert>
    using namespace std;
    
    int main() {
        
        map<int, vector <int>> someMap;
        someMap[5] = {5, 2, 3, 7};
        someMap[151] = {5, 9, 20};
        //iterate through each element of the map
        for(const std::pair<int, std::vector<int>> &myPair: someMap)
        {
            //make sure the vector is not empty
            assert(!myPair.second.empty());
            
            //print the last element in the vector
            std::cout << myPair.second.back() <<std::endl;
        }
        return 0;
    }
    

    上述程序的输出为:

    7
    20
    

    可以看到here

    【讨论】:

    • for-loop 看起来就像回到 2011 年。最好使用 structured binding。这种情况是结构化绑定的教科书用例。
    • 这是不错的代码。它在语义和性能方面与结构化绑定 1 是 100% 等效的。 C++17 相对较新,许多生产代码很旧并且仍在使用 C++11,所以这个答案在 2021 年肯定仍然有价值。我个人非常喜欢结构化绑定之一,我发现它更具可读性和更容易解析由人类。我推荐它,但这并不意味着我认为 C++11 绝对不好。此外,明确这一点确实是有效的,尽管我个人尝试在明确和简洁之间找到平衡。
    • @AnoopRana 由于可维护性问题,这错误代码。假设您要将someMap 更改为map&lt;int64_t, vector&lt;int&gt;&gt;。如果您忘记编辑循环怎么办?使用-Wrange-loop-construct,您可以在灾难发生之前发现错误。但如果你不这样做呢?然后令人震惊的是,这将编译:map&lt;int64_t, vector&lt;int&gt;&gt; m{{7, {1}}}; for (const pair&lt;int, vector&lt;int&gt;&gt; &amp;x : m) cout &lt;&lt; x.first &lt;&lt; ' ' &lt;&lt; x.second.back() &lt;&lt; '\n'; 没有-Wrange-loop-construct 你得到没有警告。祝你好运调试为什么键被破坏。 auto 和结构化绑定避免了此类问题。
    • 实际上,使用例如999999999999ll 作为键(上图)而不是 7 会使问题更加明显。在这种情况下,输出是-727379969 1(除非它是UB,此时它可以是任何东西)。忘记编辑循环是一个容易犯的错误,尤其是当数据类型定义和循环在不同的文件中,在不同的“API 端”等时。结构化绑定省去了许多繁琐且容易出错的循环编辑,并防止许多这些错误都是从一开始就发生的。
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 2013-01-24
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    相关资源
    最近更新 更多