如何合并两个 STL 地图?

发布于 2024-09-17 07:05:18 字数 106 浏览 8 评论 0原文

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

寄居人 2024-09-24 07:05:19

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

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

将执行您想要的操作, 我认为。

(编辑:如果您使用的是 C++17 或更高版本,请考虑以下答案:https://stackoverflow.com/a/56594603/ 118150

工作示例:

#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

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

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

will do what you want, I think.

(EDIT: If you are using C++17 or newer, consider this answer: https://stackoverflow.com/a/56594603/118150)

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
半葬歌 2024-09-24 07:05:19

如果要将条目从一个映射复制到另一个映射,可以使用 std::mapinsert

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

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

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 的旧数据,并且 < code>targetMap 将是两个映射的合并,优先考虑 sourceMap 的条目。

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

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

But note that insert does 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.:

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 insert the target into the source and std::swap the results:

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

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

两仪 2024-09-24 07:05:19

C++17

正如 John Perry 的回答中提到的,自从 C++17 std::map 提供了 merge() 成员函数。 merge() 函数为目标地图生成与 jkerian 的解决方案 基于使用的相同结果insert(),如您所见下面的例子是我从 jkerian 借来的。我刚刚使用一些 C++11 和 C++17 功能更新了代码(例如使用类型别名基于范围的 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;
}

输出:

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 code> 来自 bar,这样 bar 中就只剩下 2:203:30

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

Coliru 上的代码

C++17

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

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

As you can see, merge() also gives priority to the target map foo when keys overlap. If you want to have it the other way round, then you have to call 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:40 from bar, so that only 2:20 and 3:30 remain in bar.

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>.

Code on Coliru

遥远的绿洲 2024-09-24 07:05:19

请注意,从 C++17 开始,有一个 merge()< /code>地图方法。

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

何时共饮酒 2024-09-24 07:05:19

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

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

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

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

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

如果 goodKeys 和 betterKeys 中有任何等效的键,则 betterKeys 的“值”将被保留。

According to ISO/IEC 14882:2003, section 23.1.2, Table 69, expression 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;

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<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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文