J'ai du code qui a une séquence de if
s qui fonctionne, mais je me sens juste en désordre. Fondamentalement, je veux choisir le plus grand des trois entiers et définir un indicateur d'état pour indiquer celui qui a été choisi. Mon code actuel ressemble à ceci:
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;
Ce modèle se produit plusieurs fois, et avec des noms de variables longs, il devient un peu difficile de confirmer visuellement que chacun if
est correct. Je pense qu'il pourrait y avoir un moyen meilleur et plus clair de le faire; quelqu'un peut-il suggérer quelque chose?
Il existe des doublons potentiels, mais ils ne correspondent pas tout à fait à cette question.
Dans le doublon suggéré: Approches pour vérifier plusieurs conditions? toutes les solutions suggérées semblent aussi maladroites que le code d'origine, donc elles ne fournissent pas une meilleure solution.
Et ce post Des façons élégantes de gérer si (sinon) d'autre ne concerne que les niveaux d'imbrication et l'asymétrie, ce qui n'est pas le problème ici.
la source
Réponses:
Factoriser la logique, revenir tôt
Comme suggéré dans les commentaires, il suffirait de simplement encapsuler votre logique dans une fonction et de sortir tôt avec
return
les afin de simplifier beaucoup les choses. De plus, vous pouvez factoriser un peu de fonctionnalité en déléguant des tests à une autre fonction. Plus concrètement:C'est plus court que ma précédente tentative:
Ce qui précède est un peu plus détaillé, mais il est facile à lire à mon humble avis et ne recalcule pas les comparaisons plusieurs fois.
Confirmation visuelle
Dans votre réponse, vous dites:
... aussi, dans votre question, vous dites:
Je ne comprends peut-être pas ce que vous essayez de réaliser: voulez-vous copier-coller le motif partout où vous en avez besoin? Avec une fonction comme celle ci-dessus, vous capturez le motif une fois, et vous vérifiez une fois pour tout ce que toutes les comparaisons utilisent
a
,b
etc
comme requis. Ensuite, vous n'avez plus à vous inquiéter lorsque vous appelez la fonction. Bien sûr, dans la pratique, votre problème est peut-être un peu plus complexe que celui que vous avez décrit: si c'est le cas, veuillez ajouter des détails si possible.la source
MOSTLY_A
ouMOSTLY_C
en casa == c
eta > b
. C'est corrigé. Merci.TL: DR; Votre code est déjà correct et "propre".
Je vois beaucoup de gens se débattre autour de la réponse mais tout le monde manque la forêt à travers les arbres. Faisons toute l'informatique et l'analyse mathématique pour bien comprendre cette question.
Tout d'abord, nous notons que nous avons 3 variables, chacune avec 3 états: <, = ou>. Le nombre total de permutations est de 3 ^ 3 = 27 états, auxquels j'attribuerai un numéro unique, noté P #, pour chaque état. Ce nombre P # est un système numérique factoriel .
Enumérant toutes les permutations que nous avons:
Par inspection, nous voyons que nous avons:
Écrivons un programme (voir la note de bas de page) pour énumérer toutes ces permutations avec des valeurs pour A, B et C. Tri stable par P #:
Au cas où vous vous demandiez comment je savais quels états P # étaient impossibles, maintenant vous savez. :-)
Le nombre minimum de comparaisons pour déterminer la commande est:
Log2 (27) = Log (27) / Log (2) = ~ 4,75 = 5 comparaisons
c'est-à-dire que coredump a donné le nombre minimal correct de 5 comparaisons. Je formaterais son code comme:
Pour votre problème, nous ne nous soucions pas de tester l'égalité, nous pouvons donc omettre 2 tests.
Peu importe à quel point le code est propre / mauvais s'il obtient la mauvaise réponse, c'est donc un bon signe que vous gérez tous les cas correctement!
Ensuite, en ce qui concerne la simplicité, les gens continuent d'essayer "d'améliorer" la réponse, où ils pensent qu'améliorer signifie "optimiser" le nombre de comparaisons, mais ce n'est pas strictement ce que vous demandez. Vous avez confondu tout le monde lorsque vous avez demandé "Je pense qu'il pourrait y avoir un meilleur", mais n'avez pas défini ce que signifie "mieux". Moins de comparaisons? Moins de code? Des comparaisons optimales?
Maintenant, puisque vous posez des questions sur la lisibilité du code (étant donné l'exactitude), je ne ferais qu'une seule modification à votre code pour la lisibilité: Alignez le premier test avec les autres.
Personnellement, je l'écrirais de la manière suivante, mais cela peut être trop peu orthodoxe pour vos normes de codage:
Note de bas de page: Voici le code C ++ pour générer les permutations:
Modifications: sur la base des commentaires, déplacé TL: DR vers le haut, supprimé la table non triée, clarifié 27, nettoyé le code, décrit les états impossibles.
la source
@msw vous a dit d'utiliser un tableau au lieu de a, b, c et @Basile vous a dit de refactoriser la logique "max" en fonction. La combinaison de ces deux idées conduit à
fournir ensuite une fonction qui calcule l'indice max d'un tableau arbitraire:
et l'appelle comme
Le nombre total de LOC semble avoir augmenté par rapport à celui d'origine, mais maintenant vous avez la logique principale dans une fonction réutilisable, et si vous pouvez réutiliser la fonction plusieurs fois, cela commence à porter ses fruits. De plus, la
FindStrictMaxIndex
fonction n'est plus liée à vos "exigences métiers" (séparation des préoccupations), donc le risque que vous aurez à la modifier ultérieurement est beaucoup plus faible que dans votre version d'origine (principe ouvert-fermé). Par exemple, cette fonction ne devra pas être modifiée même si le nombre d'arguments change, ou si vous devez utiliser d'autres valeurs de retour que MOSTLY_ABC, ou si vous traitez d'autres variables que a, b, c. De plus, l'utilisation d'un tableau au lieu de 3 valeurs différentes a, b, c pourrait également simplifier votre code à d'autres endroits.Bien sûr, si dans tout votre programme il n'y a qu'un ou deux endroits pour appeler cette fonction et que vous n'avez pas d'autres applications pour conserver les valeurs dans un tableau, je laisserais probablement le code d'origine tel quel (ou utiliser @ amélioration de coredump).
la source
FindStrictMaxIndex()
ne sont peut-être pas trop propres, mais du point de vue de l'appelant, il est raisonnablement évident de ce qui est en train d'être réalisé.int
fonction typée. Mais j'accepte votre commentaire si l'on utilise un langage différent comme Python ou Perl.FindStrictMaxIndex
réutilisation de la fonction. Pour une ou deux fois de réutilisation, cela ne sera pas payant, bien sûr, mais c'est ce que j'ai déjà écrit dans ma réponse. Notez également les autres avantages que j'ai mentionnés ci-dessus concernant les changements futurs.return result[FindStrictMaxIndex(val,3)];
au point de code où les 8 lignes d'origine ont été placées . Les autres parties, en particulierFindStrictMaxIndex
elle-même, sont complètement séparées de la "logique métier", ce qui les éloigne de l'objectif de l'évolution des exigences métier.Vous devriez probablement utiliser une macro ou une fonction
MAX
donnant au maximum deux nombres.Alors vous voulez juste:
Vous avez peut-être défini
mais soyez prudent - notamment sur les effets secondaires - lorsque vous utilisez des macros (car
MAX(i++,j--)
cela se comporterait étrangement)Mieux vaut donc définir une fonction
et l'utiliser (ou au moins
#define MAX(X,Y) max2ints((X),(Y))
....)Si vous avez besoin de comprendre l'origine du MAX, vous pourriez avoir une longue macro comme celle
#define COMPUTE_MAX_WITH_CAUSE(Status,Result,X,Y,Z)
qui est une longuedo{
...}while(0)
macro, peut-êtreEnsuite, vous pouvez invoquer
COMPUTE_MAX_WITH_CAUSE(status,res,a,b,c)
à plusieurs endroits. C'est un peu moche. J'ai défini les variables localesx
,y
,z
pour réduire le mauvais effets secondaires ....la source
J'ai plus réfléchi à cela, donc comme mon problème était principalement une confirmation visuelle que toutes les comparaisons utilisaient les mêmes variables, je pense que cela pourrait être une approche utile:
Que chaque macro prend
a
,b
etc
dans le même ordre est facile à confirmer, et le nom de la macro me évite d' avoir à travailler à ce que toutes les comparaisons et ANDs font.la source