set_intersection /difference bei maps/sets
-
Hallo zusammen,
ich hab eine Frage. Wie kann ich die methoden set_intersection bzw. set_difference bei sets/maps ausführen ?
Mein Ansatz ist:
map<string,int> myMap1, myMap2, myMap3; //füllen von myMap1 & myMap2 set_intersection(myMap1.begin(),myMap1.end(),myMap2.begin(),myMap2.end(), myMap3.begin());erhalte aber immer eine Fehlermeldung

-
ist ja interessant 'set_intersection' auf map's anzuwenden

Deine Fehlermeldung ist die des Compilers, der besagt, dass er einem pair< const string, int > nichts zuwesien kann. Was ok ist, da der Iterator einer map kein Output-Iterator ist.
Als 5. Parameter von 'set_intersection' wird aber ein Output-Iterator verlangt.Versuch' mal
#include <iterator> // inserter // ... set_intersection( myMap1.begin(), myMap1.end(), myMap2.begin(), myMap2.end(), inserter( myMap3, myMap3.end() ) );Gruß
Werner
-
Jetzt funktionierts

Ist es auch möglich bei set_difference nur zu vergleichen ob die Keys übereinstimmen ?
Bis jetzt werden die Elemente nur in myMap3 geschrieben, wenn sowohl die Keys und values übereinstimmen.
Das heisst wenn in mymap1 ["der",1] steht und in mymap2["der",4] so ist "der" nicht in der Schnittmenge vorhanden, was ich aber gerne hätte.
Ist es möglich dass mit der Standardfunktion set_intersection zu erreichen ?
-
Ja, du kannst als zusätzlichen Parameter myMap1.value_comp() an die Funktion übergeben - das ist das Prädikat, mit dem die Elemente innerhalb der Map verglichen werden.
-
Also, ich hab schon etwas damit rumprobiert und es funktioniert auch "teilweise".
Was nicht funktioniert ist folgendes.
Ich habe zwei map<double,string> -Strukturen, die ich auf Gemeinsamkeiten (im string-Feld untersuchen will.Der Code den ich dafür verwende ist:
set_intersection(myMap1.begin(),myMap1.end(),myMap2.begin(),myMap2.end(),inserter(myMap3,myMap3.end()),myMap1.key_comp());mit diesem Code erhalte ich immer einen Fehler beim Compilieren.
Wenn ich stattdessen myMap1.value_comp() verwende, erhalte ich keinen Fehler beim Compilieren:
set_intersection(myMap1.begin(),myMap1.end(),myMap2.begin(),myMap2.end(),inserter(myMap3,myMap3.end()),myMap1.value_comp());Aber damit erhalte ich natürlich nicht das gewünschte Ergebnis

-
Laser schrieb:
mit diesem Code erhalte ich immer einen Fehler beim Compilieren.
Welchen Fehler?
PS: map's sind nur bezüglich des Schlüssels sortiert (bei deinem Beispiel also das double-Feld), aber nicht bezüglich des zugeordneten Wertes - also kannst du set_intersection auch nicht auf den Wert-Teil der map anwenden (jedenfalls nicht direkt).
-
mein code sieht ungefähr so aus:
map<double,string> myMap1, myMap2; set<string> entries; //füllen von myMap1 & myMap2 set_intersection( myMap1.begin(), myMap1.end(), myMap2.begin(), myMap2.end(), inserter( entries, entries.end() ),myMap1.key_comp() );und die fehlermeldung so:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -oMainMenu.o ../MainMenu.cpp /usr/include/c++/4.0.2/bits/stl_algo.h: In function ‘_OutputIterator std::set_intersection(_InputIterator1, _InputIterator1, _InputIterator2, _InputIterator2, _OutputIterator, _Compare) [with _InputIterator1 = std::_Rb_tree_iterator<std::pair<const double, std::string> >, _InputIterator2 = std::_Rb_tree_iterator<std::pair<const double, std::string> >, _OutputIterator = std::insert_iterator<std::set<std::string, std::less<std::string>, std::allocator<std::string> > >, _Compare = std::less<double>]’: ../MainMenu.cpp:367: instantiated from here /usr/include/c++/4.0.2/bits/stl_algo.h:4281: error: no match for call to ‘(std::less<double>) (std::pair<const double, std::string>&, std::pair<const double, std::string>&)’ /usr/include/c++/4.0.2/bits/stl_function.h:226: note: candidates are: bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = double] ../MainMenu.cpp:367: instantiated from here /usr/include/c++/4.0.2/bits/stl_algo.h:4283: error: no match for call to ‘(std::less<double>) (std::pair<const double, std::string>&, std::pair<const double, std::string>&)’ /usr/include/c++/4.0.2/bits/stl_function.h:226: note: candidates are: bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = double] ../MainMenu.cpp:367: instantiated from here /usr/include/c++/4.0.2/bits/stl_algo.h:4287: error: no match for ‘operator=’ in ‘__result. std::insert_iterator<_Container>::operator* [with _Container = std::set<std::string, std::less<std::string>, std::allocator<std::string> >]() = __first1. std::_Rb_tree_iterator<_Tp>::operator* [with _Tp = std::pair<const double, std::string>]()’ /usr/include/c++/4.0.2/bits/stl_iterator.h:531: note: candidates are: std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(typename _Container::const_reference) [with _Container = std::set<std::string, std::less<std::string>, std::allocator<std::string> >] /usr/include/c++/4.0.2/bits/stl_iterator.h:491: note: std::insert_iterator<std::set<std::string, std::less<std::string>, std::allocator<std::string> > >& std::insert_iterator<std::set<std::string, std::less<std::string>, std::allocator<std::string> > >::operator=(const std::insert_iterator<std::set<std::string, std::less<std::string>, std::allocator<std::string> > >&)Die Sache ist dass die Map schon nach den double-Werten sortiert sein soll weil die eine Art "Bewertung" darstellen, aber andererseits will ich gucken ob es "Einträge/Strings" gibt die in beiden Maps vorkommen (dürfen sich in den Bewertungen unterscheiden)
Könnte ja auch eine eigene set_intersection-Methode implementieren, bei der ich selber mit Iteratoren überprüfe wo die Elemente gleich sind, aber dachte dass es auch mit der STL-Methode gehen muss/sollte (die wohl effizienter ist)
-
Ups, stimmt - map::key_comp() erwartet Schlüsselwerte (in deinem Fall double's), die es vergleichen soll.
Und ja: set_intersection ist effizienter als ein linearer Vergleich, ABER es erwartet, daß der Suchbereich entsprechend dem gesuchten Kriterium sortiert ist (und eine map<double,string> ist NICHT nach den string's sortiert). Du könntest höchstens einen Umweg über einen zweiten Container verwenden:
template<typename F,typename S> bool cmp2nd(const pair<F,S>& lhs,const pair<F,S>& rhs) { return lhs.second<rhs.second; } map<double,string> map1,map2; multimap<double,string> target; //umkopieren in Vectoren: vector<pair<double,string> data1(map1.begin(),map1.end()),data2(map2.begin(),map2.end()); //diese Vectoren kannst du jetzt nach deinen eigenen Vorstellungen sortieren und mergen: sort(data1.begin(),data1.end(),cmp2nd); sort(data2.begin(),data2.end(),cmp2nd); set_intersection(data1.begin(),data1.end(),data2.begin(),data2.end(),inserter(target,target.begin()),cmp2nd);(oder du nutzt transform(), um aus jeder map die string-Hälften rauszuziehen)