Anzahl der Treffer von find_if



  • Hallo zusammen,

    ich habe in einer Funktion, die sehr oft aufgerufen wird einene std::find_if Aufruf. Nur wenn find_if einen Treffer liefert, will ich eine bestimmte Aktion ausführen, in allen anderen Fällen gebe ich eine Warnung aus.
    Leider habe ich keine Möglichkeit gefunden, die Anzahl der Treffer zu ermitteln, ausser zu iterieren und mitzählen. Dies gefällt mir aber nicht.
    Daher meine Frage, gibt es einen schönen und performanten Weg die Anzahl der Treffer zu ermitteln?

    Schöne Grüße
    Quaneu



  • find_if bricht beim ersten Vorkommen ab, benutze daher gleich count_if.



  • Danke für den Hinweis, hatte ich wohl überlesen.

    Wenn ich aber count_if benutze und ich einen Treffer bekomme, muss ich nochmal mit find_if das Element suchen, da ich dieses für die weitere Bearbeitung brauche. Ich hatte gehofft, dass es einen Aufruf gibt, mit dem ich beides bekommen, z.B. alle Suchtreffer und auf diesen hätte ich dann die Anzahl abfragen können.



  • Deine Angaben sind sehr vage: "bestimmte Aktion".

    Du wirst aber wohl entweder die Objekte oder Positionen/Iteratoren speichern oder aber mitzählen müssen.



  • Deine Angaben sind sehr vage: "bestimmte Aktion".

    Entschuldigt bitte. Ich dachte, dass es nicht wichtig ist, was ich mache. Aber es stimmt, ich hätte sagen müssen, dass ich dann auf dem Treffer Methoden aufrufen muss, wenn es nur einen Treffer gibt.

    Ok, Schade, dann bleibt mir wirklich nichts anderes übrig. Bzw. suche ich selber und benutze nicht find_if und count_if, dann habe ich nur einen Schleifendurchlauf.



  • Quaneu schrieb:

    Bzw. suche ich selber und benutze nicht find_if und count_if, dann habe ich nur einen Schleifendurchlauf.

    Bei n Treffern wird du wohl n Schleifendurchläufe haben.



  • Wenn du die Treffer selbst benötigst, dann kannst du auch remove_if, remove_copy_if mit negierter Bedingung benutzen oder aber gleich copy_if, s. <algorithm>.



  • Ich meinte ich muss nur mit einer Schleife einmal über den vector laufen und nicht zweimal ;).



  • Willst du jetzt nur auf dem ersten Treffer etwas ausführen, dann reicht find_if, ansonsten kannst du auch einfach so etwas wie for_each_if benutzen:

    template<typename Iterator, typename Pred, typename Operation>
    void for_each_if(Iterator begin, Iterator end, Pred p, Operation op)
    {
        for(; begin != end; begin++)
            if (p(*begin))
                op(*begin);
    }
    

    Wofür benötigst du dann die Anzahl der Treffer?



  • Wenn es nur einen Treffer gibt, dann will ich auf diesem "arbeiten", gibt es keinen oder mehr als einen, dann soll nichts gemacht werden.
    Das mit copy_if kommt der Sache schon sehr nahe, wobei ich immer mehr zu einer eigenen Lösung tendiere.



  • In etwa so? (iter ist letztes Element noch zu behandeln!)

    std::vecto<X> v ...
    
    auto iter = std::find_if( begin(v), end(v), ...);
    
    if( iter != end(v) && std::find_if( iter+1, ...) == end(v) ) {
        doit
    }
    else {
       nix machen
    


  • Vielen Dank für deine Lösung. Diese gefällt mir sehr gut, da sie nicht viel langsamer sein sollte als eine eigene und man benutzt Existierendes 👍



  • Wie wäre es denn mit:

    auto first = std::find_if( begin(v), end(v), ...);
    
    if( first == std::find_if( rbegin(v), rend(v), ...) ) {
        doit
    }
    else {
       nix machen
    

    ?



  • Also bei mir kompiliert es leider nicht. "==" ist das Problem. Sonst würde ich sagen, sieht es noch ein bisschen besser aus 😉


  • Mod

    Ungetestet:
    first == std::find_if( rbegin(v), rend(v), ...).base()



  • So gehts. Vielen Dank für eure Hilfe.


Log in to reply