C++ 如何合并两个 STL 映射?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3639741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:21:02  来源:igfitidea点击:

How can I merge two STL maps?

c++mergestlmapsstdmap

提问by JonF

How can I merge two STL maps into one? They both have the same key and value types (map<string, string>). If there is an overlap of the keys, I would like to give preference to one of the maps.

如何将两个 STL 映射合并为一个?它们都具有相同的键和值类型 ( map<string, string>)。如果键有重叠,我想优先选择其中一张地图。

回答by jkerian

Assuming you want to preserve the elements in mapA, and merge elements in mapBfor which there is no key in mapA:

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

mapA.insert(mapB.begin(), mapB.end())

will do what you want, I think.

会做你想做的,我想。

Working example:

工作示例:

#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;
}

output:

输出:

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

回答by kiwibonga

If you want to copy entries from one map to another, you can use std::map's insert:

如果要将条目从一张地图复制到另一张地图,可以使用std::map's insert

targetMap.insert(sourceMap.begin(), sourceMap.end());

But note that insertdoes not update elements if their key is already in targetMap; those items will be left as-is. To overwrite elements, you will have to copy explicitly, e.g.:

但请注意,insert如果元素的键已经在 targetMap 中,则不会更新元素;这些项目将保持原样。要覆盖元素,您必须显式复制,例如:

for(auto& it : sourceMap)
{
    targetMap[it.first] = it.second;
}

If you don't mind losing the data in sourceMap, another way to achieve a copy-and-overwrite is to insertthe target into the source and std::swapthe results:

如果您不介意丢失 中的数据sourceMap,另一种实现复制和覆盖的方法是insert将目标放入源和std::swap结果中:

sourceMap.insert(targetMap.begin(), targetMap.end());
std::swap(sourceMap, targetMap);

After swapping, sourceMapwill contain targetMap's old data, and targetMapwill be a merge of the two maps, with preference for sourceMap's entries.

交换后,sourceMap将包含targetMap的旧数据,targetMap并将是两个映射的合并,优先选择sourceMap的条目。

回答by John Perry

Notice that, since C++17, there is a merge()method for maps.

请注意,从 C++17 开始,就有了merge()映射的方法。

回答by honk

C++17

C++17

As mentioned in John Perry's answer, since C++17std::mapprovides a merge()member function. The merge()function produces the same result for the target map as jkerian's solutionbased on using insert(), as you can see from the following example, which I borrowed from jkerian. I just updated the code with some C++11and C++17 features (such as usingtype alias, range-based for loopwith structured binding, and list initialization):

正如John Perry's answer 中提到,因为C++17std::map提供了一个merge()成员函数。该merge()函数为目标地图生成与基于 using 的jkerian 解决方案相同的结果insert(),正如您从我从 jkerian 借用的以下示例中看到的。我刚刚用一些C++11和 C++17 特性更新了代码(例如using类型别名、具有结构化绑定的基于范围的 for 循环列表初始化):

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;
}

Output:

输出:

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

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

As you can see, merge()also gives priority to the target map foowhen keys overlap. If you want to have it the other way round, then you have to call bar.merge(foo);.

如您所见,当键重叠时,merge()也会优先考虑目标地图foo。如果你想反过来,那么你必须调用bar.merge(foo);.

However, there is a difference between using insert()and merge()regarding what happens to the source map. The insert()functions adds new entries to the target map, while merge()moves entries over from the source map. This means for the example above, that insert()does not alter bar, but merge()removes 4:40from bar, so that only 2:20and 3:30remain in bar.

但是,使用insert()merge()关于源映射发生的事情之间存在差异。这些insert()函数向目标映射添加新条目,同时merge()从源映射移动条目。这意味着对于上面的示例, thatinsert()不会改变bar,而是从 中merge()删除,因此只有和保留在 中。4:40bar2:203:30bar

Note: I reused the example from jkerian which uses map<int, int>for the sake of brevity, but merge()also works for your map<string, string>.

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

Code on Coliru

Coliru 上的代码

回答by Valentine Savchenko

According to ISO/IEC 14882:2003, section 23.1.2, Table 69, expression a.insert(i,j):

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

pre: i,j are not iterators into a. inserts each element from the range [i, j) if and only if there is no element with key equivalent to the key of that element in containers with unique keys;

pre: i,j 不是 a 的迭代器。插入范围 [i, j) 中的每个元素,当且仅当在具有唯一键的容器中没有与该元素的键等效的键的元素;

Since that std::map must follow this restriction, if you'd like to give preference to "values" from one map over another you should insert into it. For example,

由于该 std::map 必须遵循此限制,因此如果您希望将一个映射中的“值”优先于另一个映射,则应将其插入其中。例如,

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

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

So if there are any equivalent keys in goodKeys and betterKeys, "values" of the betterKeys will be preserved.

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