Development Tip

두 개의 STL 맵을 병합하려면 어떻게해야합니까?

yourdevel 2020. 11. 29. 12:23
반응형

두 개의 STL 맵을 병합하려면 어떻게해야합니까?


두 개의 STL 맵을 하나로 병합하려면 어떻게해야합니까? 둘 다 동일한 키 및 값 유형 ( map<string, string>)을 갖습니다 . 키가 겹치는 부분이 있으면지도 중 하나를 선호합니다.


의 요소를 유지하고에 키가없는 mapA요소를 병합 한다고 가정합니다 .mapBmapA

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

당신이 다른 하나 개의 맵에서 항목을 복사 할 경우, 사용할 수 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의 이전 데이터를, 그리고 targetMap선호와 함께, 두지도의 병합 될 것 sourceMap'의 항목.


C ++ 17 이후 merge()로 맵에 대한 메서드가 있습니다.


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의 "값"이 유지됩니다.


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

참고URL : https://stackoverflow.com/questions/3639741/how-can-i-merge-two-stl-maps

반응형