Nullen aus std::vector< std::vector< int > > löschen
-
ANGs_Pino schrieb:
Nur bleibt der Code hängen (Endlosschleife(???)).
..sollte er nicht. Der Code ist zwar fehlerhaft - folgen zwei Nullen hintereinander so wird die zweite nicht gelöscht - aber er bleibt deshalb nicht hängen.
Wenn so eine Konstruktion - mit gleichzeitigem Löschen von Elementen in zwei Containern - notwendig wird, so liegt wahrscheinlich ein Designfehler vor.
Statt:vector< vector< int > > MasterVector; vector< vector< int > > SlaveVector;
ist wahrscheinlich die geeignetere Variante:
struct Irgendwas // ?? { int m_master; int m_slave; }; vector< vector< Irgendwas > > MastersAndSlaves;
dann lies sich dies mit einem std::remove(_if) und anschließendem std::erase einfacher und sicherer erledigen.
Für die Profis - sowas geht dann auch:
for_each( MasterVector.begin(), MasterVector.end(), bind( &vector< int >::erase, _1, bind( &remove< vector< int >::iterator, int >, bind( &vector< int >::begin, _1 ), bind( &vector< int >::end, _1 ), 0 ), bind( &vector< int >::end, _1 ) ) );
Gruß
Werner
-
drakon schrieb:
@Nexus:
Ich würde das hier ebenfalls über die Operatoren machen und nicht über Iteratoren, weil er ja noch einen zweiten vector hat, wo er gleich mitlöschen kann,ohne sonst noch etwas berechnen zu müssen.Du hast Recht, zumal man bei
std::vector
keinen Nachteil durch Random Access hat.Werner Salomon schrieb:
Für die Profis - sowas geht dann auch
Solche Konstrukte finde ich immer interessant. Ob diese die Sache vereinfachen, bleibt dahingestellt, aber Hauptsache, es sieht gut aus.
Vielleicht solltest du aber noch erwähnen, dass man dazu Boost benötigt (wobei die Profis das wissen sollten).
-
...oder gleich vector< vector< pair<int, int> > > MastersAndSlaves;
-
for_each( MasterVector.begin(), MasterVector.end(), bind( &vector< int >::erase, _1, bind( &remove< vector< int >::iterator, int >, bind( &vector< int >::begin, _1 ), bind( &vector< int >::end, _1 ), 0 ), bind( &vector< int >::end, _1 ) ) );
So proggen nur totale Vollhupen.
-
Werner Salomon schrieb:
Für die Profis - sowas geht dann auch:
for_each( MasterVector.begin(), MasterVector.end(), bind( &vector< int >::erase, _1, bind( &remove< vector< int >::iterator, int >, bind( &vector< int >::begin, _1 ), bind( &vector< int >::end, _1 ), 0 ), bind( &vector< int >::end, _1 ) ) );
Man kann sich das Leben auch unnötig schwer machen...
Ich würde das so schreiben:#include <vector> #include <algorithm> #include <boost/foreach.hpp> int main() { std::vector<std::vector<int> > masterVector; BOOST_FOREACH(std::vector<int>& v, masterVector) v.erase(std::remove(v.begin(), v.end(), 0), v.end()); }
Finde ich etwas ... leserlicher
-
hustbaer schrieb:
Werner Salomon schrieb:
Für die Profis - sowas geht dann auch:
for_each( MasterVector.begin(), MasterVector.end(), bind( &vector< int >::erase, _1, bind( &remove< vector< int >::iterator, int >, bind( &vector< int >::begin, _1 ), bind( &vector< int >::end, _1 ), 0 ), bind( &vector< int >::end, _1 ) ) );
Man kann sich das Leben auch unnötig schwer machen...
Ich würde das so schreiben:#include <vector> #include <algorithm> #include <boost/foreach.hpp> int main() { std::vector<std::vector<int> > masterVector; BOOST_FOREACH(std::vector<int>& v, masterVector) v.erase(std::remove(v.begin(), v.end(), 0), v.end()); }
Finde ich etwas ... leserlicher
Hab ich was verpasst? Wo ist der SlaveVector hin?
-
JezMalButterBeiDieFische schrieb:
SlaveVector hin?
der heißt jetzt v.
-
Vorher wurde doch aus zwei Vektoren gelöscht und jetzt doch nur aus einem, oder?
-
JezMalButterBeiDieFische schrieb:
Vorher wurde doch aus zwei Vektoren gelöscht und jetzt doch nur aus einem, oder?
aus jedem v alle nullen.
std::vector<std::vector<int> > masterVector; BOOST_FOREACH(std::vector<int>& v, masterVector) v.erase(std::remove(v.begin(), v.end(), 0), v.end());
ist
std::vector<std::vector<int> > masterVector; for(auto i=masterVector.begin();i!=masterVector.end();++i)) std::vector<int>& v=*i; v.erase(std::remove(v.begin(), v.end(), 0), v.end());
std::remove(v.begin(), v.end(), 0) schmeißt sozusagen alle nullen raus, naja, löschen kann die funktion nicht. was sie aber kann, ist die nullen ans ende schieben und die richtigen werte an den anfang. und sie gibt zurück, wo nach dem umverschieben die nullen anfangen.
v.erase(woDieNullenANfangen); löscht dann die ganzen nullen.
-
aber das ist doch immer nur ein vector pro for-schleife, vorher waren es zwei in einer schleife.
-
JezMalButterBeiDieFische schrieb:
aber das ist doch immer nur ein vector pro for-schleife, vorher waren es zwei in einer schleife.
in remove steckt innendrin eine schleife.
-
Ne er hat schon Recht - vorher gab's zwei Schleifen UND zwei std::vector.
Der "slave Vector" is weg, weil ... den irgendwer mal weggelassen hat.
Mein Code bezog sich bloss auf das "bind-Monster" von Werner -- dass man das halt wesentlich einfacher (und kürzer) schreiben kann.BTW: in C++0x wird's ja gottseidank lambda-expressions geben, dann muss man kaum mehr "binden".
-
Wie würde das denn mit Lambda-Ausdrücken aussehen? Wäre es dann tatsächlich einfacher bzw. übersichtlicher?
-
ca. gleich wie die BOOST_FOREACH variante, nur ohne den "Hack" üder das Marko eben:
for_each(MasterVector.begin(), MasterVector.end(), [](std::vector<int>& v) { v.erase(std::remove(v.begin(), v.end(), 0), v.end()); });