【问题标题】:How to get the first n elements of a std::map如何获取 std::map 的前 n 个元素
【发布时间】:2010-12-21 00:31:06
【问题描述】:

由于 C++ std::map 中没有 .resize() 成员函数,我想知道,如何获得最多包含 n 个元素的 std::map。

显而易见的解决方案是创建一个从 0 到 n 的循环,并使用第 n 个迭代器作为 std::erase() 的第一个参数。

我想知道是否有任何不需要循环的解决方案(至少在我的用户代码中不需要)并且更像是“STL 方式”。

【问题讨论】:

  • 嗯.. 我会说使用迭代器循环 STL 方式,不是吗?
  • 没有std::erase。使用std::map<Key,Val,Pred,Alloc>::erase()

标签: c++ resize stdmap shrink


【解决方案1】:

您可以为此使用std::advance( iter, numberofsteps )

【讨论】:

    【解决方案2】:

    几乎任何容器的通用解决方案,例如 std::list、std::map、boost::multi_index。您必须只检查地图的大小。

    template<class It>
    It myadvance(It it, size_t n) {
       std::advance(it, n);
       return it;
    }
    
    template<class Cont>
    void resize_container(Cont & cont, size_t n) {
        cont.erase(myadvance(cont.begin(), std::min(n, cont.size())), 
                     cont.end());
    }
    

    【讨论】:

    • 它是 void std::advance(),所以没有编译。
    • +1,但如果你要整理它以供发布,你必须下定决心 resize_container 的作用是什么概念。函数和模板参数名称建议任何容器。函数参数名称建议任何映射。正如所写的那样,我认为它实际上可以在任何序列或关联容器上工作,不幸的是,这意味着它的域是 C++ 分类中的一个多系群。
    • 这听起来是不是有点自命不凡? ;-) 我的意思是“可擦除”或任何不是 C++ 容器分类方式的自然部分,因为序列和关联容器都有自己的几乎但不完全兼容的 erase 函数。
    【解决方案3】:

    正确的方法是使用 std::advance。但这是一种有趣(缓慢)的方式,允许“在地图上使用调整大小”。更一般地说,这种技巧可用于处理矢量但不适用于地图的其他事情。

    map<K,V> m; //your map
    vector< pair<K,V> > v(m.begin(), m.end());
    v.resize(n);
    m = map<K,V>(v.begin(),v.end());
    

    【讨论】:

      【解决方案4】:

      为什么要调整地图大小?

      地图中的元素不按任何顺序存储 - 第一个“n”实际上没有任何意义

      编辑:
      有趣的是 std::map 确实有顺序,不确定这个概念有多大用处。
      条目是否与键的排序顺序相同?
      那是什么意思?如果您有由 SSN 键入的姓名,这是否意味着姓名按 SSN 数字顺序存储?

      【讨论】:

      • 元素不是按键排序的吗?
      • 不是你想的那样,元素在内存中是按某种顺序排列的。有一种哈希算法可以将键转换为索引。但是 key1 和 key2 的元素不一定是相邻的。
      • @mgb 不,那将是一个哈希表。 std::map 是二叉搜索树(通常是特定的红黑树)。因此,std::map 中的元素的存储方式使得按顺序迭代变得简单快捷。
      • 我的想法和安德烈亚斯·布林克一样。我确实将一些结果存储在地图中,并希望找出最适合的 n 个元素。这就是为什么我会扔掉其余的。 (所以实际上,我不会调整大小,我会缩小地图。)但是如果我做对了,我会得到一个 my n 结果,但不能保证它们是具有最小键值的 n?跨度>
      • @Adhemar:我的帖子来得太晚了。感谢您澄清这一点。
      【解决方案5】:

      std::map 不是列表。没有“前 n”个元素。

      顺便说一句:如果容器被更改,迭代器将变得无效。

      如果你真的需要一个更小的地图,你可以迭代它并将所有元素添加到一个新的地图中。

      【讨论】:

      • 嗯,元素是按它们的键排序的,不是吗?
      • @Nailer:很好,我不知道。此链接确认:cplusplus.com/reference/stl/map
      • 是的,他们是。但是地图“最有可能实现为(平衡)节点树”(引用“C++ 编程语言”,Bjarne Stroustrup),而不是列表。所以 mymap[n] 没有任何意义。
      • 根据 sgi 的文档,std::map 的迭代器在容器更改后不会变得无效:“Map 具有将新元素插入地图的重要属性 使指向现有元素的迭代器无效。从映射中删除一个元素也不会使任何迭代器无效,当然,实际上指向被删除元素的迭代器除外。" - - sgi.com/tech/stl/Map.html
      • 迭代器失效(或不失效)在这里无关紧要。我们将使用 map.erase(iterator1, iterator2),任何“迭代器失效”问题都会使该函数无法使用,我们假设 STL 函数并非无法使用;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-23
      • 2011-04-12
      • 2016-04-25
      • 2014-09-17
      相关资源
      最近更新 更多