Vérifier exactement un jeu d’options booléen

Eh bien, c’est une sorte de hacky:

function b2n(boo) { return boo ? 1 : 0; } if(b2n(opt1) + b2n(opt2) + b2n(opt3) !== 1) { throw new Error("Exactly one option must be set"); } 

Y a-t-il une meilleure façon de faire cela en Javascript? En utilisant l’un des

  • traitement booléen / numérique plus intelligent
  • tableau sournois ou opérations fonctionnelles

Et ainsi de suite. Les solutions JavaScript et Node sont les bienvenues

Dans mon problème actuel, les options viennent du commandant du module Node. Je ne traite donc pas de vrais problèmes, mais de vérités et de faussetés. Il peut y avoir une solution de commandant aussi.

En supposant que vous ayez un tableau d’options, vous pouvez faire:

 if(opts.filter(Boolean).length !== 1) {} 

Il me semble cependant que vous devriez avoir une variable avec trois états possibles à la place …

 var opt = 'a'; // (or 'b', or 'c') 

Tu peux le faire :

 if ( !!opt1 + !!opt2 + !!opt3 !== 1 ) { 

Ça marche parce que

  • !! crée un booléen à partir de n’importe quelle valeur ( true si les objects sont évalués comme true dans if(value) )
  • en ajoutant des booléens, vous obtenez 1 pour true et 0 pour false .

Vous avez mentionné dans votre commentaire que cela provenait d’un object d’options de commandant.

Vous pouvez le faire plus élégamment avec Lodash :

 if (_(options).values().compact().size() === 1) 

Si vous voulez seulement compter un sous-ensemble des options, vous pouvez insérer

 .pick('a', 'b', 'c') 
 if ([opt1, opt2, opt3].reduce(function(x, y) { return x + !!y }, 0) == 1) { // exactly one }; 

ECMAScript 5 réduire la fonction.

Je pense que vous êtes trop intelligent, quel est le problème avec:

 var optionsSelected = 0; if( opt1 ) optionsSelected++; if( opt2 ) optionsSelected++; if( opt3 ) optionsSelected++; if( optionsSelected !== 1 ) { throw new Error("Exactly one option must be set"); } 

Bien sûr, je peux aussi jouer au jeu intelligent:

  if( opts.filter(Boolean).length !== 1 ) { throw new Error("Exactly one option must be set"); } 

@spudly est sur la bonne voie, mais cela pourrait être un peu plus compact:

 if( [opt1,opt2,opt3].filter(function(x){return x}).length!==1 ) { throw new Error("Exactly one option must be set"); } 

Voir la méthode de filtrage de ES5 pour plus d’informations.