【问题标题】:How can I concatenate two C++ maps如何连接两个 C++ 映射
【发布时间】:2011-03-01 14:54:40
【问题描述】:

如何连接以下两个地图?

map<string, map<string,string>> map1;
map<string, map<string,string>> map2;

我只想将map2 添加到map1 并保留map1 中已有的所有元素,即在map1 的末尾添加map2。我试过map1.insert(map2.begin(), map2.end()),但它不起作用,因为它覆盖了map1 中的旧元素。

【问题讨论】:

  • “它不起作用” - 它确实起作用。这就是 std::map 的定义方式:键值对的集合,按唯一键排序。
  • 您是否也想保留map2 中的所有元素?
  • 如果我已经将这些元素添加到 map1,为什么还要这样做?

标签: c++ dictionary merge insert concat


【解决方案1】:

map 一个键只能包含一个值。例如,尝试使用multimap<>

【讨论】:

    【解决方案2】:

    这个问题与地图的概念相矛盾。如果您在地图中插入一个值,您希望它位于“正确的位置”,具体取决于它的键。这意味着每个键只有一个条目。

    相反,您可以使用vector&lt; pair&lt; mymap::key, myamap::value &gt; &gt; 并用第一个相应的条目填充它。第二张地图。

    map< string, int > map1, map2;
    ... fill the maps
    vector< pair<string, int> > concatted;
    concatted.insert( map1.begin(), map1.end() );
    concatted.insert( map2.begin(), map2.end() );
    

    【讨论】:

    • 但这不会创建两个不同的地图,即包含地图[0]、地图[1]的列表...我想要做的就是在for循环中将地图附加到另一个地图。
    • @Niklas:这就是重点:您不能附加两个地图。您可以创建“联合”,但重复输入会丢失。
    • insert() 方法需要一个 positon 在哪里插入范围作为第一个参数:... concatted.insert( concatted.begin(), map1.begin(), map1.end() ); ...
    【解决方案3】:

    用一个简单的for循环来做:(虽然我喜欢在合理的地方使用stl算法):

    for(std::map<...>::const_iterator it = map2.begin(), it_end = map2.end(); it != it_end; ++it)
       map1.insert(*it);
    

    任何其键已经在 map1 中的元素不会被覆盖,因为 map::insert 不会被覆盖。

    【讨论】:

    • 所以它在概念上会“覆盖”map2 中的条目。回到 sqr 1?
    • 阙?它不会以任何方式修改 map2。
    【解决方案4】:

    如果地图不是太大,则相反:

    map2.insert(map1.begin(), map1.end());
    map1 = map2;
    

    这将覆盖map2 中的重复值,但会保留map1 中的值(我知道这是您想要的)。

    【讨论】:

    • 其实,为什么insert with a range会替换而insert with one element不呢?
    【解决方案5】:

    如果您只想合并它们,但如果发生冲突,请保留 map1 中的元素,然后只需反转地图:

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

    这当然假设在合并之后,您只对结果感兴趣,而不再对旧集合感兴趣。

    【讨论】:

      【解决方案6】:

      由于C++17std::map提供了merge()成员函数,所以你可以简单地调用map1.merge(map2);。请注意,地图是按其键排序的,因此元素不一定会附加在末尾。此外,由于映射中的键是唯一的,因此并非所有来自 map2 的元素都可能插入到 map1 中。完整示例:

      int main() {
          std::map<std::string, std::map<std::string, std::string>> map1{
              {"a", {{"b", "b"}}}, {"b", {{"c", "c"}}}
          };
      
          std::map<std::string, std::map<std::string, std::string>> map2{
              {"b", {{"x", "x"}}}, {"c", {{"y", "y"}}}
          };
      
          map1.merge(map2);  // C++17
      
          std::cout << "map1:" << std::endl;
          for (auto const &kv : map1)
              std::cout << kv.first << ": " << kv.second.begin()->first << std::endl;
      
          std::cout << std::endl << "map2:" << std::endl;
          for (auto const &kv : map2)
              std::cout << kv.first << ": " << kv.second.begin()->first << std::endl;
      
          return 0;
      }
      

      输出:

      地图1:
      一个:b
      b: c
      c: 是的

      地图2:
      b: x

      如您所见,当键重叠时,merge() 不会覆盖目标映射 map1 中的现有元素。如果要优先考虑来自map2 的元素,则必须调用map2.merge(map1);。您还可以看到,merge() 将条目从源映射中移出。无法合并的元素保留在map2

      Code on Coliru

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多