Ich habe einen Code mit einer Folge von if
s, die funktionieren, aber ich fühle mich einfach chaotisch. Grundsätzlich möchte ich die größte von drei Ganzzahlen auswählen und ein Statusflag setzen, um zu sagen, welche ausgewählt wurde. Mein aktueller Code sieht folgendermaßen aus:
a = countAs();
b = countBs();
c = countCs();
if (a > b && a > c)
status = MOSTLY_A;
else if (b > a && b > c)
status = MOSTLY_B;
else if (c > a && c > b)
status = MOSTLY_C;
else
status = DONT_KNOW;
Dieses Muster tritt einige Male auf, und bei langen Variablennamen wird es etwas schwierig, visuell zu bestätigen, dass jedes if
korrekt ist. Ich denke, es könnte einen besseren und klareren Weg geben, dies zu tun. kann jemand etwas vorschlagen?
Es gibt einige potenzielle Duplikate, die jedoch nicht ganz mit dieser Frage übereinstimmen.
Im vorgeschlagenen Duplikat: Ansätze zur Überprüfung mehrerer Bedingungen? Alle vorgeschlagenen Lösungen scheinen genauso ungeschickt zu sein wie der ursprüngliche Code, daher bieten sie keine bessere Lösung.
Und dieser Beitrag Elegante Möglichkeiten, wenn (falls sonst) sonst nur Verschachtelungsebenen und Asymmetrie behandelt werden, was hier nicht das Problem ist.
quelle
Antworten:
Logik faktorisieren, früh zurückkehren
Wie in den Kommentaren vorgeschlagen, würde es ausreichen, Ihre Logik einfach in eine Funktion einzuschließen und frühzeitig mit
return
's zu beenden, um die Dinge erheblich zu vereinfachen. Sie können auch ein wenig Funktionalität berücksichtigen, indem Sie Tests an eine andere Funktion delegieren. Konkreter:Dies ist kürzer als mein vorheriger Versuch:
Das Obige ist etwas ausführlicher, aber meiner Meinung nach leicht zu lesen und berechnet Vergleiche nicht mehrmals neu.
Visuelle Bestätigung
In Ihrer Antwort sagen Sie:
... auch in Ihrer Frage sagen Sie:
Ich verstehe möglicherweise nicht, was Sie erreichen möchten: Möchten Sie das Muster überall dort kopieren und einfügen, wo Sie es benötigen? Mit einer Funktion wie der obigen erfassen Sie das Muster einmal und überprüfen einmal, ob alle Vergleiche verwendet werden
a
,b
undc
nach Bedarf. Dann brauchen Sie sich keine Sorgen mehr zu machen, wenn Sie die Funktion aufrufen. Natürlich ist Ihr Problem in der Praxis vielleicht etwas komplexer als das von Ihnen beschriebene: Wenn ja, fügen Sie bitte nach Möglichkeit einige Details hinzu.quelle
MOSTLY_A
oderMOSTLY_C
für den Falla == c
und zurückkommena > b
. Dies ist behoben. Vielen Dank.TL: DR; Ihr Code ist bereits korrekt und "sauber".
Ich sehe viele Leute, die um die Antwort waffeln, aber jeder vermisst den Wald durch die Bäume. Lassen Sie uns die gesamte Informatik und mathematische Analyse durchführen, um diese Frage vollständig zu verstehen.
Zunächst stellen wir fest, dass wir 3 Variablen mit jeweils 3 Zuständen haben: <, = oder>. Die Gesamtzahl der Permutationen beträgt 3 ^ 3 = 27 Zustände, wobei ich jedem Zustand eine eindeutige Zahl mit der Bezeichnung P # zuweisen werde. Diese P # -Nummer ist ein Fakultätsnummernsystem .
Aufzählung aller Permutationen, die wir haben:
Durch Inspektion sehen wir, dass wir haben:
Schreiben wir ein Programm (siehe Fußnote), um alle diese Permutationen mit Werten für A, B und C aufzulisten. Stabile Sortierung nach P #:
Falls Sie sich gefragt haben, woher ich weiß, welche P # -Zustände unmöglich sind, wissen Sie jetzt. :-)
Die Mindestanzahl von Vergleichen zur Bestimmung der Reihenfolge beträgt:
Log2 (27) = Log (27) / Log (2) = ~ 4,75 = 5 Vergleiche
dh Coredump ergab die korrekte 5 minimale Anzahl von Vergleichen. Ich würde seinen Code wie folgt formatieren:
Für Ihr Problem ist es uns egal, ob wir auf Gleichheit prüfen, daher können wir zwei Tests weglassen.
Es spielt keine Rolle, wie sauber / schlecht der Code ist, wenn er die falsche Antwort erhält. Dies ist ein gutes Zeichen dafür, dass Sie alle Fälle korrekt behandeln!
Der Einfachheit halber versuchen die Leute immer wieder, die Antwort zu "verbessern", wobei sie denken, dass Verbesserung bedeutet, die Anzahl der Vergleiche zu "optimieren", aber das ist nicht genau das, was Sie fragen. Sie haben alle verwirrt, bei denen Sie gefragt haben: "Ich glaube, es könnte ein besseres geben", aber nicht definiert, was "besser" bedeutet. Weniger Vergleiche? Weniger Code? Optimale Vergleiche?
Da Sie nun nach der Lesbarkeit des Codes fragen (bei korrekter Richtigkeit), würde ich nur eine Änderung an Ihrem Code vornehmen, um die Lesbarkeit zu gewährleisten: Richten Sie den ersten Test an den anderen aus.
Persönlich würde ich es folgendermaßen schreiben, aber dies ist möglicherweise zu unorthodox für Ihre Codierungsstandards:
Fußnote: Hier ist der C ++ - Code zum Generieren der Permutationen:
Bearbeitungen: Basierend auf Feedback, TL: DR nach oben verschoben, unsortierte Tabelle entfernt, 27 geklärt, Code bereinigt, unmögliche Zustände beschrieben.
quelle
@msw hat Ihnen gesagt, dass Sie ein Array anstelle von a, b, c und verwenden sollen. @Basile hat Ihnen gesagt, dass Sie die "max" -Logik in eine Funktion umgestalten sollen. Die Kombination dieser beiden Ideen führt zu
Stellen Sie dann eine Funktion bereit, die den maximalen Index eines beliebigen Arrays berechnet:
und nenne es wie
Die Gesamtzahl der LOC scheint sich gegenüber der ursprünglichen erhöht zu haben, aber jetzt haben Sie die Kernlogik in einer wiederverwendbaren Funktion, und wenn Sie die Funktion mehrmals wiederverwenden können, beginnt sie sich auszuzahlen. Darüber hinaus ist die
FindStrictMaxIndex
Funktion nicht mehr mit Ihren "Geschäftsanforderungen" verwoben (Trennung von Bedenken), sodass das Risiko, dass Sie sie später ändern müssen, viel geringer ist als in Ihrer ursprünglichen Version (Open-Closed-Prinzip). Diese Funktion muss beispielsweise nicht geändert werden, auch wenn sich die Anzahl der Argumente ändert oder andere Rückgabewerte als MOSTLY_ABC verwendet werden müssen oder Sie andere Variablen als a, b, c verarbeiten. Darüber hinaus kann die Verwendung eines Arrays anstelle von 3 verschiedenen Werten a, b, c Ihren Code auch an anderen Stellen vereinfachen.Wenn es in Ihrem gesamten Programm nur ein oder zwei Stellen gibt, an denen diese Funktion aufgerufen werden kann, und Sie keine weiteren Anwendungen zum Speichern der Werte in einem Array haben, würde ich den ursprünglichen Code wahrscheinlich so lassen, wie er ist (oder verwendet wird) @ coredumps Verbesserung).
quelle
FindStrictMaxIndex()
mögen nicht zu sauber sein, aber aus der Sicht des Anrufers ist es ziemlich offensichtlich, was versucht zu erreichen.int
typisierte Funktion. Aber ich stimme Ihrem Kommentar zu, wenn man eine andere Sprache wie Python oder Perl verwendet.FindStrictMaxIndex
Funktion wiederverwendet werden kann. Bei ein oder nur zwei Wiederverwendungen zahlt sich das natürlich nicht aus, aber das habe ich bereits in meiner Antwort geschrieben. Beachten Sie auch die anderen Vorteile, die ich oben in Bezug auf zukünftige Änderungen erwähnt habe.return result[FindStrictMaxIndex(val,3)];
an der Stelle im Code, an der die ursprünglichen 8 Zeilen platziert wurden, durch einen einfachen Einzeiler ersetzt werden können . Die anderen Teile, insbesondereFindStrictMaxIndex
selbst, sind vollständig von der "Geschäftslogik" getrennt, wodurch sie aus dem Fokus sich ändernder Geschäftsanforderungen herauskommen.Sie sollten wahrscheinlich ein Makro oder eine Funktion verwenden
MAX
, die maximal zwei Zahlen enthält.Dann wollen Sie einfach:
Sie könnten definiert haben
Seien Sie jedoch vorsichtig - insbesondere in Bezug auf Nebenwirkungen -, wenn Sie Makros verwenden (da
MAX(i++,j--)
sich dies seltsam verhalten würde).Definieren Sie also besser eine Funktion
und benutze es (oder zumindest
#define MAX(X,Y) max2ints((X),(Y))
....)Wenn Sie den Ursprung des MAX verstehen müssen, haben Sie möglicherweise ein langes Makro, wie
#define COMPUTE_MAX_WITH_CAUSE(Status,Result,X,Y,Z)
es vielleicht ein langesdo{
...}while(0)
Makro istDann könnten Sie
COMPUTE_MAX_WITH_CAUSE(status,res,a,b,c)
an mehreren Stellen aufrufen . Es ist ein bisschen hässlich. Ich definierte lokale Variablenx
,y
,z
schlechte Nebenwirkungen zu senken ....quelle
Ich habe mehr darüber nachgedacht. Da mein Problem hauptsächlich die visuelle Bestätigung war, dass alle Vergleiche dieselben Variablen verwendeten, denke ich, dass dies ein nützlicher Ansatz sein könnte:
Dass jeder Makro nimmt
a
,b
undc
in der gleichen Reihenfolge , ist einfach zu bestätigen, und der Makroname spart mich mit, herauszufinden , was alle Vergleiche und ANDs tun.quelle