Frage zu Standardlösung für das Löschen gleicher Elemente am vectorende



  • @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. 😉


  • Mod

    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());
    

Anmelden zum Antworten