[STL] Map in Vector "swappen" ??
-
names.push_back( namemap[i] );Ist leider alles was mir einfällt...
-
Dann machs per iterator.
-
STL Noob schrieb:
Danke, aber ne sorry.
Ich will nur den Wert kopieren.map<int, string> namemap; vector<string> names;Geht das ned?

Meinerseits

WAS möchtest Du ? Welchen "Wert" ?
Dein Sourcebeispiel funktioniert natürlich problemlos, "kopiert" aber nichts, sondern legt einfach nur eine Map (namens "namemap") und einen vector (namens "names") an und deren Inhalte haben nichts gemeinsam....Gruß,
Simon2.
-
#include <string> #include <map> #include <vector> #include <algorithm> using namespace std; template<typename Container> struct MapValueBackInserter{ MapValueBackInserter(Container & cont):m_cont(cont){} template<typename T> void operator()(T & pair){ m_cont.push_back(pair.second); } private: Container & m_cont; }; int main() { map<int,string> mymap; vector<string> myvec; for_each(mymap.begin(),mymap.end(),MapValueBackInserter<vector<string> >(myvec)); return 0; }
-
Bin jetzt zwar zu spät weil ich zwischendrin was gegessen hab
,gebe aber trotzdem noch meinen Senf dazu.#include <iostream> #include <string> #include <map> #include <list> #include <iterator> using namespace std; template <class T1_,class T2_,class dest_container_type> class cross_inserter :public std::iterator<std::output_iterator_tag,void,void,void,void> { public: explicit cross_inserter(dest_container_type& s_) :value_set(s_){} cross_inserter& operator= (std::pair<const T1_,T2_> p_) { value_set.insert(value_set.end(),p_.second); return *this; } cross_inserter& operator*() {return *this;} cross_inserter& operator++() {return *this;} cross_inserter& operator++(int) {return *this;} private: dest_container_type& value_set; }; int main() { map<int,string> foo; foo[0] = "eins"; foo[1] = "zwei"; foo[2] = "drei"; list<string> bar; cross_inserter<int,string,list<string> > ci(bar); copy(foo.begin(),foo.end(),ci); list<string>::iterator it = bar.begin(); while(it!= bar.end()) { cout<<*it<<endl; ++it; } return 0; }MfG Spacelord
-
Spacelord, Genial!

Was geht eingentlich am schnellsten?
for( iterator it = namemap.begin(); it != namemap.end(); ++it ) // oder for( int i = 0; i < namemap.size(); ++i )? { names.push_back( namemap[i] ); }oder
foreach und dem Back Inserter von evillisimo?
Oder mit copy und Spacelords Variante?
-
Ahaaaa !!!
Anhand der Beispiele vom Chefkoch und dem Lord ist mir auch klar, was gesucht ist !
[quote="Simon2"]STL Noob schrieb:
Danke, aber ne sorry.
Ich will nur den Wert kopieren.
..."Wert" als Gegensetz zu "Key" ....

Danke für die Erhellung,
Simon2.
P.S.: Nur der Vollständigkeit halber: Im Ergebnisvektor sind die Werte natürlich nicht mehr eindeutig. Mag gewollt und bewusst sein - wollte es nur für den Fall der Fälle anmerken....
-
Simon2 schrieb:
...
P.S.: Nur der Vollständigkeit halber: Im Ergebnisvektor sind die Werte natürlich nicht mehr eindeutig. Mag gewollt und bewusst sein - wollte es nur für den Fall der Fälle anmerken....Die Werte sind doch in der Map schon nicht eindeutig, ein Wert kann unter mehreren Keys vorkommen, ist mir durchaus bewusst, aber das wird nicht der Fall sein.
Was ist denn eurer Meinung nach am günstigsten?
-
STL Noob schrieb:
...Die Werte sind doch in der Map schon nicht eindeutig, ein Wert kann unter mehreren Keys vorkommen, ist mir durchaus bewusst, aber das wird nicht der Fall sein....
Dann ist ja alles klar.

Ich hatte halt vermutet (und Du hast es bestätigt: "... wird nicht der Fall sein..."), dass Du implizit davon ausgehst, dass ein find() auf den Ergebnisvector auch ein eindeutiges Ergebnis liefert. (z.B. sehr schön versteckt, wenn Du implizit davon ausgehst, dass sich in Deinem vector "size()-viele IDs" befinden....)Aber wenn Dir das klar ist und Du überall damit umgehst, ist ja alles OK - wollte es nur in Erinnerung bringen.
STL Noob schrieb:
...
...Was ist denn eurer Meinung nach am günstigsten?Ich würde schätzen, dass sich die Dinger alle nicht viel tun. Sie werden im Wesentlichen zu demselbe Code compiliert, der eben die Map Element für Element durchgeht und ein vector<>::push_back() durchführt (ebenso wie Deine selbstgeschriebene "Schlaufe"
).
Ist eher eine Geschmacksfrage.Gruß,
Simon2.
-
ok

Dann mach ichs simpel mit der selbstgeschriebenen "Schlaufe" (Was ist an dem Wort so witzig?
) Da finde ich ersichtlicher was geht, wenn ich den Code anschau.
Eventuell ein Reserve mit der Grösse der Mappe davor dürfte noch was bringen, denk ich..map<int, string> namemap; vector<string> names; int names_cnt = namemap.size(); names.reserve( names_cnt ); for( int i = 0; i < names_cnt; ++i ) { names.push_back( namemap[i] ); }Danke allen für die tollen Lösungen und Tipps

-
War da nicht grad noch ein Beitrag von loooolllll?
Was stand da? Als ich ihn angucken wollte, war er weg..
-
Schlaufe
Schleife
Map != Mappe
-
Und warum wurde das gelöscht?
Ist doch nett mich darauf hin zu weisen..
-
hier noch eine variante mit adaptern:
template<typename T, typename U> struct mem_ref_t : public std::unary_function< T, U& > { explicit mem_ref_t(U T::* p) : p_( p ) {} U& operator()(T& ref) const { return ref.*p_; } const U& operator()(const T& ref) const { return ref.*p_; } U T::* p_; }; template<typename T, typename U> mem_ref_t< T, U > mem_ref(U T::* p) { return mem_ref_t< T, U >( p ); } int main() { using namespace std; map<int, string> namemap; vector<string> names; int names_cnt = namemap.size(); names.reserve( names_cnt ); transform( namemap.begin(), namemap.end(), back_inserter( names ), mem_ref( &map<int, string>::value_type::second ) ); }
-
STL Noob schrieb:
Und warum wurde das gelöscht?
Ist doch nett mich darauf hin zu weisen..Das wurde gelöscht weil der sich in dem Post nur lustig darüber gemacht hat. Und nicht verbessert hat.
BR
Vinzenz
-
Ok. Lustig machen kann ich mich selbst. Für mich sind Schlaufe und Schleife das selbe, halt ein nett gefaltetes Stoffband zB..
camper schrieb:
hier noch eine variante mit adaptern:
template<typename T, typename U> struct mem_ref_t : public std::unary_function< T, U& > { explicit mem_ref_t(U T::* p) : p_( p ) {} U& operator()(T& ref) const { return ref.*p_; } const U& operator()(const T& ref) const { return ref.*p_; } U T::* p_; }; template<typename T, typename U> mem_ref_t< T, U > mem_ref(U T::* p) { return mem_ref_t< T, U >( p ); } int main() { using namespace std; map<int, string> namemap; vector<string> names; int names_cnt = namemap.size(); names.reserve( names_cnt ); transform( namemap.begin(), namemap.end(), back_inserter( names ), mem_ref( &map<int, string>::value_type::second ) ); }
Versteh ich nicht.
Was bedeuten denn T:: im Konstruktor?Bei all den vielen Varianten weis ich gar nicht mehr, warum ich das machen wollte
nein quatsch, ich weis nicht mehr welche ich nehmen soll. Die sind alle schön, aber was ist schnell?
-
die idee ist, ein funktionsobjekt zu bauen, dass für ein gegebenes (pair-)objekt den zweiten member extrahiert:
template<typename T, typename U> struct ExtractSecond { string& operator()(std::pair<int,string>& p) const { return p.second; } const string& operator()(const std::pair<int,string>& p) const { return p.second; } };damit können wir ein einfach transform benutzen:
transform( namemap.begin(), namemap.end(), back_inserter( names ), ExtractSecond() );der rest ist nichts weiter als eine generalisierung im stile der standard adapter mem_fun_ref & co.
U T::* p;deklariert einen pointer auf ein member der klasse T vom typ U
die notwendigkeit, einen eigenen adapter zu benötigen, ist auch einem designfehler der standardbibliothek geschuldet - wäre der zugriff auf die einzelelemente von vornherein durch memberfunktionen geregelt, könnte man standardadapter benutzen (vgl. boost::compressed_pair)
prinzipiell sind alle vorgestellten lösungen potenmtiell gleich schnell, es kommt letzlich auf die qualität deines compilers an. eine forschleife bzw. for_each sind dabei für den optimierer wahrscheinlich noch am leichtesten zu verarbeiten, aber prinzipiell müsstest du schon messen, um eine definitive antwort zu erhalten.
P.S. kleiner spaß: auch in vc++8.0 gibt es noch jede menge ICEs
struct X { int& x; }; void foo() { mem_ref( &X::x ); }
-
STL Noob schrieb:
Die sind alle schön, aber was ist schnell?
Wie bereits mehrfach erwähnt werden die sich wohl alle nicht viel tun aber wenn es denn wirklich auf jede Nanosekunde ankommt, wären speziell für die Lösungen vom Chefkoch und mir noch Spezialisierungen für einzelne Containertypen angemessen.
Die Art wie der Zielcontainer "arbeitet" ist sicherlich mitentscheidend für die Performance der Lösungen.MfG Spacelord
-
STL Noob schrieb:
...ich weis nicht mehr welche ich nehmen soll. Die sind alle schön, aber was ist schnell?

Ich persönlich finde es sehr schön, dass es so viele Stile und Möglichkeiten in C++ gibt, etwas umzusetzen.
Mein Tipp:
- Nimm die Variante, die Du am besten verstehst, bzw. die Dir am übersichtlichsten erscheint (nicht vergessen, dass man ca. 60% der Entwicklungszeit damit verbringt, Sourcecode zu "verändern" (anpassen, korrigieren, erweitern, ...)).
- Mach Dir um Performance Gedanken, wenn es soweit ist (sprich: Du festgetellt hast, dass es zu langsam ist).

Wenn es Dich wirklich interessiert, kannst Du ja alle Varianten implementieren und Performancemessungen durchführen (wobei ich - wie gesagt - immer noch davon überzeugt bin, dass ein (guter) Compiler aus allen Varianten mehr oder minder denselben Code macht => alle gleich schnell sind; zumindestens bei einfachen Datentypen).
Gruß,
Simon2.