【问题标题】:Append and replace the contents of one map to another map?将一张地图的内容附加并替换到另一张地图?
【发布时间】:2017-06-23 21:23:41
【问题描述】:

所以我知道map1.insert(map2.begin(), map2.end()); 会将map2 的所有元素插入map1

但是map2 的某些元素可能已经存在于map1 中。这些元素不会更新。

e.g. map1 has { 3 : 4, 6 : 7 }
     map2 has { 11: 5, 6 : 0 }

     Now if I do map1.insert(map2.begin(), map2.end()), I will get
     map1 = { 3: 4, 6 : 7, 11 : 5 }

     But what I want is
     map1 = { 3: 4, 6 : 0, 11 : 5 }

我想知道有没有像map1.insert(map2.begin(), map2.end()); 这样强制更新已经存在的密钥的函数?

更新: 我知道可以使用:map1[k] = v 来完成 map2 中的所有键值对。

但是有没有像map1.insert(map2.begin(), map2.end()) 这样的函数可以做到这一点?

【问题讨论】:

  • 第 1 步:为 map2 中的每个元素在 map 1 中查找第 2 步:如果找到 No Op 第 3 步:如果未找到则插入
  • 对于 map2 中的所有键值对,看起来就像 map1[k] = v 一样简单。
  • 没有像 ``map1.insert(map2.begin(), map2.end())'' 这样的函数吗?否则可以使用 map1[k] = v
  • 你关注map2之后的内容吗?
  • 借助 C++17 支持,您可以将 insert_or_assignfor_each 和 lambda 一起使用,但对我来说,这比简单的免费函数要复杂得多。

标签: c++ stl unordered-map unordered


【解决方案1】:

在 C++17 中,先合并然后交换。

map2.merge(map1);
map2.swap(map1);

与基于插入的变体相比,这样做的好处是它只是拼接节点;不分配,不赋值,不构造。

【讨论】:

  • 啊。我只是忽略了map::merge(),并通过map2.insert(move(map1.extract(it++))) 上的循环自己想出了一种方法。
【解决方案2】:

你可以做相反的事情,然后交换。

map2.insert(map1.begin(), map1.end()); std::swap(map1, map2);

【讨论】:

    【解决方案3】:
    template<typename MapT>
    void join_inplace(MapT& m1, MapT const& m2)
    {
        for (auto p : m2)
            m1[p.first] = p.second;
    }
    

    Ideone

    编辑

    因为你不关心map2

    template<typename MapT>
    void join_inplace(MapT& target, MapT& other)
    {
        for (auto& p : other)
            target[std::move(p.first)] = p.second;
    }
    
    【解决方案4】:

    既然你不关心map2之后的状态,你可以移动它的元素

    template<typename MapT>
    void join_inplace(MapT& map1, MapT &&map2)
    {
      for(auto& p : map2)
        map1.insert_or_assign(std::move(p.first), std::move(p.second));
      map2.clear();
    }
    

    它不需要映射类型是默认可构造的(与基于map::operator[] 的解决方案不同)。

    【讨论】:

      【解决方案5】:

      这是一个 C++17 解决方案,它避免了任何分配、复制或移动(键和映射类型)

      template<typename MapT>
      void join_inplace(MapT&map1, MapT&&map2)
      {
        for(auto it=map1.begin(), end=map1.end(); it!=end;)
          map2.insert(std::move(map1.extract(it++)));
        std::swap(map1,map2);
      }
      

      解释。

      1. map::extract(it) 提取 node 从而使迭代器 it 无效。因此,我们必须像往常一样通过map1.extract(it++) 而不是在for 循环中对迭代器进行后增量。
      2. map::insert(node_type&amp;&amp;) 插入节点 iff 密钥未知。
      3. 否则节点被销毁
      4. 最后,我们必须交换地图(根据 valentindavid 的 answer)。

      注意。正是在我写这个答案的过程中,T.C. 的等效但更简单的answer出现了。我刚刚用我的 for 循环实现了map::merge()

      【讨论】:

      • 注意:这工作。如果密钥已经存在,则应该更新它。追加和替换.
      猜你喜欢
      • 2010-11-07
      • 1970-01-01
      • 2017-12-25
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多