合并两个STL贴图

时间:2010-09-03 21:42:50

标签: c++ stl maps

如何将两个STL地图合并为一个?它们都具有相同的键值类型(map)。如果键有重叠,我想优先考虑其中一个地图。

5 个答案:

答案 0 :(得分:110)

假设您要保留mapA中的元素,并合并mapB中没有键的mapA中的元素:

mapA.insert(mapB.begin(), mapB.end())
我认为

会做你想做的事。

工作示例:

#include <iostream>
#include <map>

void printIt(std::map<int,int> m) {
    for(std::map<int,int>::iterator it=m.begin();it!=m.end();++it)
        std::cout << it->first<<":"<<it->second<<" ";
    std::cout << "\n";
}

int main() {
    std::map<int,int> foo,bar;
    foo[1] = 11; foo[2] = 12; foo[3] = 13;
    bar[2] = 20; bar[3] = 30; bar[4] = 40;
    printIt(foo);
    printIt(bar);
    foo.insert(bar.begin(),bar.end());
    printIt(foo);
    return 0;
}

输出:

:!./insert
1:11 2:12 3:13
2:20 3:30 4:40
1:11 2:12 3:13 4:40

答案 1 :(得分:28)

如果您要将条目从一个地图复制到另一个地图,可以使用std::map的{​​{1}}:

insert

但请注意,targetMap.insert(sourceMap.begin(), sourceMap.end()); 如果其键已经存在于targetMap中,则不会更新元素。这些物品将保持原样。要覆盖元素,您必须明确复制,例如:

insert

如果您不介意丢失for(auto& it : sourceMap) { targetMap[it.first] = it.second; } 中的数据,另一种实现复制和覆盖的方法是sourceMap目标进入源代码并insert结果:

std::swap

交换后,sourceMap.insert(targetMap.begin(), targetMap.end()); std::swap(sourceMap, targetMap); 将包含sourceMap的旧数据,targetMap将合并两张地图,并优先选择targetMap条目。

答案 2 :(得分:10)

请注意,自C ++ 17以来,地图有merge()方法。

答案 3 :(得分:3)

根据ISO / IEC 14882:2003,第23.1.2节,表69,表达式a.insert(i,j):

  

pre:i,j不是迭代器。插入范围中的每个元素   [i,j]当且仅当没有元素与key相当于   具有唯一键的容器中该元素的键;

由于std :: map必须遵循此限制,如果您想优先考虑从一个地图到另一个地图的“值”,则应插入其中。例如,

std::map<int, int> goodKeys;
std::map<int, int> betterKeys;

betterKeys.insert(goodKeys.begin(), goodKeys.end());

因此,如果goodKeys和betterKeys中存在任何等效键,则将保留betterKeys的“值”。

答案 4 :(得分:0)

C ++ 17

John Perry's answer中所述,由于C++17 std::map提供了merge()成员函数。 merge()函数基于jkerian's solution使用insert()为目标地图生成与C++11相同的结果,如下面的示例所示,我是从jkerian借来的。我刚刚使用一些using type alias和C ++ 17功能(例如range-based for loopstructured bindinglist initializationCode on Coliru)更新了代码:

using mymap = std::map<int, int>;

void printIt(const mymap& m) {
    for (auto const &[k, v] : m)
        std::cout << k << ":" << v << " ";
    std::cout << std::endl;
}

int main() {
    mymap foo{ {1, 11}, {2, 12}, {3, 13} };
    mymap bar{ {2, 20}, {3, 30}, {4, 40} };
    printIt(foo);
    printIt(bar);
    foo.merge(bar);
    printIt(foo);
    return 0;
}

输出:

  

1:11 2:12 3:13
  2:20 3:30 4:40
  1:11 2:12 3:13 4:40

如您所见,当键重叠时,merge()也会优先考虑目标映射foo。如果您想反过来使用它,则必须致电bar.merge(foo);

但是,使用insert()merge()对于源映射会发生什么有所不同。 insert()函数将新条目添加到目标映射中,而merge()函数将条目从源映射中移出。这意味着在上面的示例中,insert()不会更改bar,但是merge()会从4:40中删除bar,因此只有2:203:30保留在bar中。

注意:为简洁起见,我重用了jkerian的示例,该示例使用map<int, int>,但是merge()也适用于您的map<string, string>

https://codepen.io/anon/pen/dBYwpP