Wie kann ich zwei STL-Karten zu einer zusammenführen? Sie haben beide die gleichen Schlüssel- und Werttypen ( map<string, string>
). Bei einer Überlappung der Tasten möchte ich einer der Karten den Vorzug geben.
Antworten:
Angenommen, Sie möchten die Elemente in beibehalten mapA
und Elemente zusammenführen, mapB
für die es keinen Schlüssel gibt mapA
:
mapA.insert(mapB.begin(), mapB.end())
werde machen was du willst, denke ich.
(BEARBEITEN: Wenn Sie C ++ 17 oder neuer verwenden, berücksichtigen Sie diese Antwort: https://stackoverflow.com/a/56594603/118150 )
Arbeitsbeispiel:
#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;
}
Ausgabe:
:!./insert
1:11 2:12 3:13
2:20 3:30 4:40
1:11 2:12 3:13 4:40
value_comp()
, der Standard jedoch nicht Mandat das.)
Wenn Sie Einträge aus einer Karte auf eine andere kopieren möchten, können Sie std::map
‚s insert
:
targetMap.insert(sourceMap.begin(), sourceMap.end());
Beachten Sie jedoch, dass insert
Elemente nicht aktualisiert werden, wenn sich ihr Schlüssel bereits in targetMap befindet. Diese Elemente bleiben unverändert. Um Elemente zu überschreiben, müssen Sie explizit kopieren, z.
for(auto& it : sourceMap)
{
targetMap[it.first] = it.second;
}
Wenn es Ihnen nichts ausmacht, die Daten zu verlieren sourceMap
, können Sie insert
das Ziel auch in die Quelle und std::swap
die Ergebnisse kopieren und überschreiben :
sourceMap.insert(targetMap.begin(), targetMap.end());
std::swap(sourceMap, targetMap);
Enthält nach dem Tauschen sourceMap
die targetMap
alten Daten und targetMap
ist eine Zusammenführung der beiden Karten, wobei die sourceMap
Einträge bevorzugt werden .
Beachten Sie, dass es seit C ++ 17 eine merge()
Methode für Karten gibt.
Wie in John Perrys Antwort erwähnt , bietet C ++ 17 std::map
eine merge()
Mitgliedsfunktion. Die merge()
Funktion erzeugt das gleiche Ergebnis für die Zielkarte wie die Lösung von jkerian basierend auf der Verwendung insert()
, wie Sie aus dem folgenden Beispiel sehen können, das ich von jkerian ausgeliehen habe. Ich habe gerade den Code mit einigen C ++ 11- und C ++ 17-Funktionen aktualisiert (z. B. using
Typalias , bereichsbasierte for-Schleife mit strukturierter Bindung und Listeninitialisierung ):
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;
}
Ausgabe:
1:11 2:12 3:13
2:20 3:30 4:40
1:11 2:12 3:13 4:40
Wie Sie sehen können, wird merge()
der Zielkarte auch Priorität eingeräumt, foo
wenn sich Schlüssel überschneiden. Wenn Sie es umgekehrt haben möchten, müssen Sie anrufen bar.merge(foo);
.
Es gibt jedoch einen Unterschied zwischen der Verwendung insert()
und der merge()
Frage, was mit der Quellkarte geschieht. Die insert()
Funktionen fügen der Zielkarte neue Einträge hinzu, während merge()
Einträge von der Quellkarte verschoben werden. Dieses Mittel für das obige Beispiel, das insert()
nicht ändert bar
, aber merge()
entfernt 4:40
von bar
, so dass nur 2:20
und 3:30
bleibt in bar
.
Hinweis: Ich habe das Beispiel von jkerian wiederverwendet, das map<int, int>
der Kürze halber verwendet wird, aber merge()
auch für Sie funktioniert map<string, string>
.
Gemäß ISO / IEC 14882: 2003, Abschnitt 23.1.2, Tabelle 69, Ausdruck a.insert (i, j):
pre: i, j sind keine Iteratoren in a. fügt jedes Element aus dem Bereich [i, j) genau dann ein, wenn in Containern mit eindeutigen Schlüsseln kein Element mit einem Schlüssel vorhanden ist, der dem Schlüssel dieses Elements entspricht;
Da diese std :: map dieser Einschränkung folgen muss, sollten Sie sie einfügen, wenn Sie "Werte" von einer Map gegenüber einer anderen bevorzugen möchten. Zum Beispiel,
std::map<int, int> goodKeys;
std::map<int, int> betterKeys;
betterKeys.insert(goodKeys.begin(), goodKeys.end());
Wenn es also äquivalente Schlüssel in goodKeys und betterKeys gibt, bleiben die "Werte" der betterKeys erhalten.