Alle Elemente im Container gleich?



  • Kommt ohne Schleife aus

    pardon? Intern...?



  • DocShoe schrieb:

    Was ist mit equal_range ? Kommt ohne Schleife aus und terminiert beim ersten Mismatch.

    Ich glaub ich würd dich zur Erschießung vorschlagen, wenn du mir sowas anbötest. 🙂



  • Bieten die STL Container -- ausgenommen vielleicht unordered_* -- nicht von sich aus schon relationale Operatoren an?!



  • DocShoe schrieb:

    Was ist mit equal_range ? Kommt ohne Schleife aus und terminiert beim ersten Mismatch.

    1. Nur für sortiert
    2. equal_range nutzt intern lower_bound und upper_bound, was der binary-search-Version von find entspricht. Man hätte also keinen Gewinn, nur mehr overhead.

    krümelkacker schrieb:

    Bieten die STL Container -- ausgenommen vielleicht unordered_* -- nicht von sich aus schon relationale Operatoren an?!

    Nur für Vergleiche zwischen zwei Containern. Hier geht es aber darum, die Elemente innerhalb eines Containers zu vergleichen.

    mismatch ist schon das Beste.



  • Sone schrieb:

    pardon? Intern...?

    Interessiert niemanden, alle vorgeschlagenen Moeglichkeiten basieren auf Schleifen. Koennten aber auch end-rekursiv implementiert sein. Duerfen sie laut Standard rekursiv sein?



  • Selber einen ALgo schreiben? 😕 👍



  • knivil schrieb:

    Sone schrieb:

    pardon? Intern...?

    Interessiert niemanden, alle vorgeschlagenen Moeglichkeiten basieren auf Schleifen. Koennten aber auch end-rekursiv implementiert sein. Duerfen sie laut Standard rekursiv sein?

    Except where explicitly specified in this standard, it is implementation-defined which functions in the Standard C++ library may be recursively reentered.

    Das ist alles, was überhaupt zu Rekursion in dem Library-Abschnitt steht.

    Also ja, das dürfen sie wahrscheinlich. Ist schließlich alles Implementationsspezifisch.



  • Also wenn sortiert, würde ich einfach front() auf back()-Gleichheit prüfen.

    Sonst geht's wohl nicht einfacher als mit nem std::algorithm + nem kleinen Lambda, ich bin immer noch für V1.



  • Ich finde seldons Variante am elegantesten.

    Auch wenn ein QC-Kommentar in allen Fällen sowieso angebracht ist.



  • Sone schrieb:

    Ich finde seldons Variante am elegantesten.

    Ja, du findest Write-Only-Code generell elegant 😉 Ich musste seldons Code etwa 20 Sekunden lang anschauen, bis ich verstanden habe, was er überhaupt tut. Die zusätzliche Abfrage auf empty() verwirrt nur noch mehr.

    krümelkacker schrieb:

    Bieten die STL Container -- ausgenommen vielleicht unordered_* -- nicht von sich aus schon relationale Operatoren an?!

    Was bringt das hier? Um zwei Container zu vergleichen, müsste ich ja eine Kopie erstellen.

    knivil schrieb:

    Nur weil es viele Moeglichkeiten gibt? Nein. Was soll an deiner Variante 1 kompliziert sein?

    Nein, weil die simpelste Möglichkeit bereits Lambda-Ausdrücke (mit Capture) erfordert. Schlussendlich hat man recht viel Boilerplate-Syntax.

    Ausserdem drückt man mit ihr aus: "prüfe für alle Elemente, ob sie gleich dem ersten Element sind". Das ist aber ein Implementierungsdetail, schöner wäre "prüfe alle Elemente auf Gleichheit". Muss ich halt selbst eine Abstraktionsebene höher schreiben.

    Eisflamme schrieb:

    ich bin immer noch für V1.

    Ja, ich machs jetzt auch so, kleinstes Übel. Oder bei Negation mit std::any_of und !=.

    - z0r0id 😮



  • Ja, du findest Write-Only-Code generell elegant

    Nein. Schon gar nicht in Anwendungscode. Ich finde nur die Syntax von Lambdas (gerade so direkt in der Argumentenliste) sehr hässlich und nicht literarisch.

    Ich musste seldons Code etwa 20 Sekunden lang anschauen, bis ich verstanden habe, was er überhaupt tut.

    Ich nicht, ich kenne den Trick schon längst. Und den STL-Algorithmus.

    Die zusätzliche Abfrage auf empty() verwirrt nur noch mehr.

    Hä? Die ist nur optional, für alle die es so brauchen.



  • Kommt schon.

    std::all_of(c.begin(), c.end(), [&c] (T elem) { return elem == c.front(); })
    

    vs

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

    Das ist doch kein Vergleich.
    Mit using namespace std; davor:

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

    Kommentiert muss der Code in beiden Fällen werden.



  • Nein, weil die simpelste Möglichkeit bereits Lambda-Ausdrücke (mit Capture) erfordert. Schlussendlich hat man recht viel Boilerplate-Syntax

    Akzeptiert, lambda ist tatsaechlich Boilerplate.



  • 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)
    

Anmelden zum Antworten