Frage zu Standardlösung für das Löschen gleicher Elemente am vectorende
-
Richtig, richtig, Denkfehler meinerseits; ich meine natürlich pop_back.
Ansonsten kann man das natürlich in
auto not_zero = std::bind2nd(std::not_equal_to<int>(), 0); v.erase(std::find_if(v.rbegin(), v.rend(), not_zero).base(), v.end());aufteilen, aber wenn man schon bei C++11 ist, geht's auch mit
v.erase(std::find_if(v.rbegin(), v.rend(), [](int x) { return x != 0; }).base(), v.end());
-
Nur mal ne Frage: Wenn die Nullen sowieso schon am Ende des vectors liegen, warum kannst du den vector nicht einfach entsprechend verkleinern und fertig?
-
seldon schrieb:
Ansonsten kann man das natürlich in
auto not_zero = std::bind2nd(std::not_equal_to<int>(), 0); v.erase(std::find_if(v.rbegin(), v.rend(), not_zero).base(), v.end());aufteilen
Könnte man nicht auch die Position der ersten 0 oder der letzten nicht-0 oder der letzen von hinten gezählten 0 als Zwischenergebnis nehmen?
-
dot schrieb:
Nur mal ne Frage: Wenn die Nullen sowieso schon am Ende des vectors liegen, warum kannst du den vector nicht einfach entsprechend verkleinern und fertig?
Weil ich ja wissen um, um wie viel der vector verkleinert werden muss aka wie viele Nullen sich am Ende befinden
-
@volkard: Du kannst als Zwischenergebnis nehmen, wozu du lustig bist.
@dot: Etwa
v.resize(std::distance(v.begin(), std::find_if(v.rbegin(), v.rend(), std::bind2nd(std::not_equal_to<int>(), 0)).base()));? Klar, das geht auch. Volkard wird es aber wahrscheinlich aus den gleichen Gründen für eine Parodie halten.

-
boost::algorithm::trim_right_if( v, std::bind2nd( std::equal_to<int>(), 0 ) );
-
Ihr macht wieder alles reichlich kompliziert...
Ich würde das ohne zu überlegen sofort so (ähnlich) schreiben wie cooky451:
while (!vec.empty() && vec.back() == 0) vec.pop_back();Bzw. wenn schon mit Boost, dann gleich so:
boost::trim_right_if(v, boost::lambda::_1 == 0);Oder so:
boost::trim_right_if(v, [](int i) {return i == 0;} );
-
volkard schrieb:
Der pop_back-Schleife würde ich aber auch nicht trauen.
Wieso nicht?
-
hustbaer schrieb:
volkard schrieb:
Der pop_back-Schleife würde ich aber auch nicht trauen.
Wieso nicht?
Weil ich viele push_back-Schleifen geschrieben habe und alles war gut. Aber noch nie eine pop_back-Schleife. Darum fühlt sich die für mich komisch an. Und das && in der Laufbedingung scheint mir dann zu einem doppelten Test in der Hauptschleife zu führen, der in find_if nicht steckt.
Andererseits, wenn es typischerweise wenige oder gar keine Nullen sind, drängt sich mir die pop_back-Schleife doch auf.
-
seldon schrieb:
v.resize(std::distance(v.begin(), std::find_if(v.rbegin(), v.rend(), std::bind2nd(std::not_equal_to<int>(), 0)).base()));? Klar, das geht auch. Volkard wird es aber wahrscheinlich aus den gleichen Gründen für eine Parodie halten.

Jupp. Weil es drei Aufrufe sind, die nacheinander geschehen und das Ergebnis sukzessive aufbauen.
auto positon_der_ersten_null_am_ende=std::find_if(v.rbegin(), v.rend(), std::bind2nd(std::not_equal_to<int>(), 0)).base(); auto anzahl_der_nicht_nullen_am_anfang=std::distance(v.begin(),positon_der_ersten_null_am_ende); v.resize(anzahl_der_nicht_nullen_am_anfang);
-
volkard schrieb:
hustbaer schrieb:
volkard schrieb:
Der pop_back-Schleife würde ich aber auch nicht trauen.
Wieso nicht?
Weil ich viele push_back-Schleifen geschrieben habe und alles war gut. Aber noch nie eine pop_back-Schleife. Darum fühlt sich die für mich komisch an. Und das && in der Laufbedingung scheint mir dann zu einem doppelten Test in der Hauptschleife zu führen, der in find_if nicht steckt.
Andererseits, wenn es typischerweise wenige oder gar keine Nullen sind, drängt sich mir die pop_back-Schleife doch auf.Ich gehe davon aus dass
a) der Code der pop_back() Schleife sowieso nahezu ideal wird (wieso sollte es da zu einem doppelten Test kommen - .back() ist ja unchecked)
und
b) es völlig egal wäre, selbst wenn die Schleife 10x so lange brauchen würde wie optimal möglich
-
Also ab ca. 50,000,000 kann man einen deutlichen Unterschied messen (52 zu 70 ms). Aber ob so viele Nullen jetzt realistisch sind..
-
Hier noch ein Beispiel für C++0X - läuft so auch auf VC++ 2010
std::vector<int> v; ... auto r = std::find_if(v.rbegin(), v.rend(), [](int t){return t!=0;}); auto new_size = std::distance(v.begin(), r.base()); v.resize(new_size);Mit bindgedingens finde ich das irgendwie unleserlicher. Aber das ist nur mein persönlicher Eindruck.
-
cooky451 schrieb:
Also ab ca. 50,000,000 kann man einen deutlichen Unterschied messen (52 zu 70 ms). Aber ob so viele Nullen jetzt realistisch sind..
Unterschied zu welcher Version?
Zu find -> distance -> resize?ps: bei MSVC wird u.U. auch _SECURE_SCL mit reinspielen, denn wenn _SECURE_SCL == 1 (default), dann ist vector::back() "checked". Kommt dann drauf an, wie gut MSVC das optimieren kann...
-
hustbaer schrieb:
Unterschied zu welcher Version?
Schleife (egal welche) gegen
v.erase(std::find_if(v.rbegin(), v.rend(), std::bind2nd(std::not_equal_to<int>(), 0)).base(), v.end());