Alle Elemente im Container gleich?



  • Sone schrieb:

    Kommentiert muss der Code in beiden Fällen werden.

    Es geht hier nicht um die Codelänge. Selbst mit Kommentar schaut man eine Weile drauf, bevor man kapiert, was da abgeht. Die erste Version ist bereits viel klarer. Noch klarer wäre allerdings eine Schleife.



  • Noch klarer wäre allerdings eine Schleife

    Jein.

    Vergleich: In der Funktionalen Programmierung will man weg von expliziter Rekursion. Warum ... weil man schauen muss, wo der rekursive Aufruf passiert, auf den ersten Blick unklar ist, wie und was bei der Rekursion so alles passiert. Man hat aber Rekursionspattern durch fold-left und fold-right. Keine explizite Rekursion mehr, Rekursionschema ist klar, was passiert, wird durch die Akkumulatorfunktion beschrieben. Rekursionsschema und "Usercode"/Akkumulatorfunktion sind klar getrennt.

    Gleiches gilt fuer Schleifen. Der Schleifenkopf kann ja durchaus viele verschiedene Formen annehmen. Warum sich ueber sowas Gedanken machen, durch die Algorithmen ist ein Iterationsschema vorgegeben. Im Falle von std::accumulate/all_of/... brauche ich nur das Praedikat/Accumulatorfunktion anzuschauen um zu wissen, was abgeht.

    Naja, Schleifen sind im Vergleich zu Rekursion vielleicht einfacher. Trotzdem versuche ich immer Iterationsschema der expliziten Iteration vorzuziehen. Sehr dankbar bin ich deswegen fuer:

    for(auto x: container)
    

    Iteratoren selbst sind mir meist zu viel Tiparbeit. Auch fuer lambda bin ich in diesem Zusammenhange dankbar, da es mir das Schreiben von Funktoren erspart.



  • otze schrieb:

    Sone schrieb:

    Kommentiert muss der Code in beiden Fällen werden.

    Es geht hier nicht um die Codelänge.

    Darum ging es mir gar nicht! 🙂 Ich habe das nur angemerkt, dass sie kommentiert werden sollten.

    Selbst mit Kommentar schaut man eine Weile drauf, bevor man kapiert, was da abgeht.

    Genau dafür sind Kommentare da: Man muss die Zeile gar nicht angucken, das Kommentar sagt, was sie tun.



  • Fuer intuitive bedienbare Programme gibt es auch Handbuecher. Liesst du die?



  • Klare Sache:

    std::is_sorted(c.begin(), c.end(), [] (int a, int b) { return a != b; });
    

    Damit gibt's sogar gleich ein debug-assert sobald der Container nicht sortiert ist. Da spart man sich die manuelle Prüfung!



  • != ist keine strikt weak ordering.



  • Also ich bin ja fuer:

    begin == end || (std::sort(begin, end), std::unique(begin, end) == begin + 1)
    


  • @Kellerautomat: Um auch Unterstützung für nicht-RA-Iteratoren zu bekommen, nutze std::next .



  • Noe, std::sort braucht RA.



  • Kellerautomat schrieb:

    Noe, std::sort braucht RA.

    💡



  • knivil schrieb:

    != ist keine strikt weak ordering.

    Daher das hilfreiche debug assert. 😉



  • Für Mathematiker:

    set{c.begin(), c.end()}.size() <= 1
    


  • Bashar schrieb:

    Für Mathematiker:

    set{c.begin(), c.end()}.size() <= 1
    

    Das ist schön! 👍



  • Wie waere es mit rotate_copy + equal?



  • Bashar schrieb:

    Für Mathematiker:

    set{c.begin(), c.end()}.size() <= 1
    

    Das ist schön, aber hat unnötig hohe Komplexität und kein Short Circuit.

    Sone schrieb:

    equal(begin(c), prev(end(c)), next(begin(c)))
    

    Das braucht BidirectionalIterator , theoretisch würde InputIterator ausreichen.

    Ich schlage vor:

    template<class InputIt]
    bool all_equal(InputIt first, InputIt last) {
        if(first == last) return true;
    
        typedef decltype(*first) T;
        T elem = *first++;
        return find_if(first, last, [&](const T& e) { return e != elem }) == last;
    }
    

    Wenn man die Kopie vermeiden möchte, kann man e == *first als Prädikat nehmen, aber dann braucht man wieder ForwardIterator .



  • ipsec schrieb:

    Bashar schrieb:

    Für Mathematiker:

    set{c.begin(), c.end()}.size() <= 1
    

    Das ist schön, aber hat unnötig hohe Komplexität und kein Short Circuit.

    Ich denke mal, spätestens seit der sort-unique-Lösung sind wir beim spaßigen Teil des Abends angelangt...



  • And the winner is...



  • knivil schrieb:

    Noch klarer wäre allerdings eine Schleife

    Jein.

    Vergleich: In der Funktionalen Programmierung...

    Oh Entschuldige. Ich war nicht im exakt Modus. Das haben wir gleich:

    "Noch klarer wäre allerdings in C++ eine Schleife".

    C++ bietet kein kurze und klare Syntax für die hier gnannten Sachen im funktionalen Programmierstil. Funktionale Programmierung in C++ ist deswegen low-level total hässlich. Natürlich verbietet dir niemand eine schön funktionale Implementation von equal_elements zu machen, aber unterhalb dieser Abstraktion ist die klarste Lösung eben die Schleife.

    template<class Range>
    bool all_equal(Range const& range){
        for(auto& x: range){
            if(x != range.front())
                return false;
        }
        return true;
    }
    


  • *auto&



  • Danke. kann gut sein, ich verwende keine c++11 features. Ich korrigiere das mal 🙂


Anmelden zum Antworten