Elemente einer std::map anhand eines Prädikats löschen
-
Hi,
ich will bestimmte Elemente einerstd::map
anhand eines Prädikats löschen. Allerdings habe ich mit dem eigentlichen löschen ein Problem. Jedeserase
könnte ja den Suchbaum neu ausbalancieren. Wenn ich nun mit einer for-Schleife und dem begin-Iterator über alle Elemente gehe, wird doch der Iterator, den mirbegin(map)
geliefert hat, ungültig, sobald ich 1xerase
mache, oder? Brauch ich dann immer wieder einen neuen begin-Iterator?Hier mal ein Beispiel. Ich zähle, wie oft ein Buchstabe in einem Satz vorkommt. Alle Buchstaben, die nur 1x vorkommen, will ich dann löschen:
#include <cctype> #include <iterator> #include <map> #include <string> using namespace std; struct map_erase_predicate { unsigned min; map_erase_predicate( unsigned min ) : min(min) {} bool operator() ( const pair<char,unsigned>& p ) const { return p.second<min; } }; void map_erase_elements( map<char,unsigned>& m, const map_erase_predicate& p ) { for(auto it=begin(m); it!=end(m); ++it) // Wie muss die for-Schleife aussehen? { if( p(*it) ) { m.erase( it ); } } } int main() { string sentence = "stanleys expeditionszug quer durch afrika wird von jedermann bewundert"; map<char,unsigned> count_letters; for(auto c : sentence) { if( isalpha(c) ) ++count_letters[c]; } map_erase_elements( count_letters, map_erase_predicate(2) ); }
Die for-Schleife funktioniert so ja nicht. Wie müsste sie aussehen?
Danke im Voraus.
-
Hallo,
Durch den erase-Aufruf wird der Iterator ungültig, und daher muß man vorher inkrementieren, um einen Iterator auf das nächste Element zu erhalten.
Aber ab C++11 liefert erase einen Iterator zurück, s. http://www.cplusplus.com/reference/map/map/erase/
-
for (auto it = m.begin(); it != m.end(); ) // so muss die for-Schleife aussehen if (p(*it)) m.erase(it++); else it++;
-
Th69 schrieb:
Erasing elements in a map does not invalidate any iterators. (apart from iterators on the element that was deleted.
Ok, dann hatte ich das irgendwie falsch im Kopf. Danke euch.
-
Wie wärs mit erase und remove_if?
m.erase(remove_if(begin(m), end(m), PREDICATE), end(m));
-
Skym0sh0 schrieb:
Wie wärs mit erase und remove_if?
m.erase(remove_if(begin(m), end(m), PREDICATE), end(m));
std::remove_if
geht nicht mit assoziativen Containern.