【问题标题】:How to get the last element of an std::unordered_map?如何获取 std::unordered_map 的最后一个元素?
【发布时间】:2014-08-06 16:48:23
【问题描述】:

如何获取std::unordered_map 的最后一个元素?

myMap.rbegin()--myMap.end() 是不可能的。

【问题讨论】:

标签: c++


【解决方案1】:

无序的容器中没有“最后一个元素”。

您可能需要一个有序的容器,例如std::map 并使用 mymap.rbegin()->first 访问最后一个元素(另见 this post

编辑:

要检查您的迭代器是否即将结束,只需将其递增(并可能将其保存在临时文件中)并对照mymap.end(),或者甚至更清洁:if (std::next(it) == last)

【讨论】:

  • 谢谢。我需要一个 unordered_map 但我需要在点击 end() 之前检查我何时完成......我可以保存“以前迭代的元素”......只是寻找一些“干净的解决方案”。
  • 那你为什么不像往常一样对照end()检查你的迭代器呢?
  • 并保留之前迭代的项目?这就是我所做的。我只是想知道是否会存在一些“更清洁”。请注意,在 Windows 上,rbegin 在那里^^
  • 我对此表示怀疑,标准明确表示它在无序容器上不存在...请参阅我的编辑,在您的情况下,干净的方式就是您所做的:递增并与 end() 进行比较
  • @yerzhan7 'first' 会得到最后一个键,'second' 会得到最后一个值,选择适合你的情况
【解决方案2】:

你不能。根据定义,元素不是基于某种顺序存储的。密钥首先被散列,这就是为什么 O(1) 搜索是可能的。如果您想检查 unordered_map 中是否存在键,您可以使用以下代码:

std::unordered_map dico;
if(dico.count(key)!=0){
    //code here
}

【讨论】:

    【解决方案3】:
    std::unordered_map::iterator last_elem;
    for (std::unordered_map::iterator iter = myMap.begin(); iter != myMap.end(); iter++)
        last_elem = iter;
    // use last_elem, which now points to the last element in the map
    

    这将按照地图为您提供的任何顺序为您提供最后一个元素。

    编辑:您需要使用std::unordered_map<YourKeyType, YourValueType> 而不仅仅是std::unordered_map。我之所以这样写是因为您没有在问题中提供类型。

    或者,正如vsoftco(谢谢)所建议的那样,您可以将last_elemiter 都声明为decltype(myMap)::iterator

    (如果您使用 MSVC++ 编译器进行编译,则需要添加 typedef decltype(myMap) map_type;,然后使用 map_type::iterator 代替 decltype(myMap)::iterator。)

    【讨论】:

    • 你用的是什么编译器? MSVC++?我相信这不会用 clang 编译。
    • 你在哪里看到rbeginunordered_map
    • unordered_map 没有反向迭代器。我想知道为什么std::prev(myMap.end()) 不起作用和段错误。
    • 对不起大家——错字。我的意思是begin,不是rbegin
    • 仍然不正确,但接近:),您需要在for 循环中使用decltype(myMap)::iterator last_elem;decltype(myMap)::iterator iter
    【解决方案4】:

    在您的 cmets 中,您的目标似乎是在向前迭代时确定您是否位于最后一个元素上。这是一个比找到最后一个元素更容易解决的问题:

    template<class Range, class Iterator>
    bool is_last_element_of( Range const& r, Iterator&& it ) {
      using std::end;
      if (it == end(r)) return false;
      if (std::next(std::forward<Iterator>(it)) == end(r)) return true;
      return false;
    }
    

    以上内容适用于任何可迭代范围(包括数组、std 容器或自定义容器)。

    我们检查我们是否是end(在这种情况下,我们不是最后一个元素,并且推进是非法的)。

    如果我们不是end,我们会查看我们中的std::next 是否是end。如果是这样,我们就是最后一个元素。

    否则,我们不是。

    这不适用于不支持多次传递的迭代器。

    【讨论】:

      【解决方案5】:

      .end() 是“经过最后一个元素的元素”的迭代器。这就是为什么你在遍历地图时这样比较它的原因:

      for (auto it = myMap.begin(); it != myMap.end(); ++it) // '!=' operator here makes it possible to only work with valid elements
      {
      }
      

      所以你想要“最后一个”元素(不管它是什么,因为它并不能真正保证是无序映射中的最后一个,因为它最终取决于密钥是如何散列的以及它最终在哪个“桶”中在)。那你需要:--myMap.end()

      更具体地说,.end() 是一个函数,它返回一个迭代器,就像 .begin() 返回一个迭代器一样。由于std::unordered_map 中没有.rbegin(),因此您必须使用--(减量运算符):

      auto it = --myMap.end();
      

      访问您使用it-&gt;first 的密钥,访问您使用it-&gt;second 的值。

      【讨论】:

        【解决方案6】:

        接受的答案似乎是错误的。即使键值对未按排序顺序存储,Unordered_map 确实具有最后一个元素。由于 unored_map 的迭代器是 forwar_iterator(LegacyForwardIterator),所以找到最后一个元素的成本是 O(n)。 Yakk - 亚当给出了正确的答案。本质上,您必须从头到尾迭代容器。在每次迭代中,您必须检查下一个元素是否为 end();如果是,那么你在最后一个元素。

        您不能调用 prev(it) 或 --it。不会有语法错误,但在使用 prev(it) 或 --it 时会出现运行时错误(更可能是分段错误)。也许下一个版本的编译器可以告诉你你有一个逻辑错误。

        【讨论】:

          猜你喜欢
          • 2019-09-21
          • 1970-01-01
          • 2020-04-06
          • 1970-01-01
          • 2012-04-02
          • 2014-04-27
          • 2010-10-30
          • 2022-06-28
          • 2022-11-15
          相关资源
          最近更新 更多