154 votes

Comment raccourcir mes déclarations conditionnelles

J'ai une très longue déclaration conditionnelle comme la suivante :

if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
    // do something.
}

Je me demandais si je pouvais refactoriser cette expression/affirmation dans une forme plus concise.

Une idée sur la façon de réaliser cela ?

23 votes

Vous pouvez les mettre dans un tableau et utiliser in ?

2 votes

0 votes

Maintenant si quelqu'un pouvait vérifier lequel est le plus rapide

242voto

Yuriy Galanter Points 21066

Vous pouvez utiliser la déclaration de commutation avec le fall thru :

switch (test.type) {

  case "itema":
  case "itemb":
  case "itemc":
  case "itemd":
    // do something
}

9 votes

C'est fondamentalement la même chose que la méthode if, la méthode de l'indice du tableau est bien meilleure

0 votes

Le problème avec l'énoncé de l'interrupteur est que vous devez mettre une pause explicite pour empêcher la chute.

6 votes

@kojiro malheureusement, la bonne réponse est celle-ci, mais il est impossible d'attirer l'attention sur cela au lieu de l'astuce géniale du bitwhise-array.

242voto

Joseph Silber Points 69582

Mettez vos valeurs dans un tableau, et vérifiez si votre élément est dans le tableau :

if ([1, 2, 3, 4].includes(test.type)) {
    // Do something
}

Si un navigateur que vous prenez en charge ne dispose pas de l'option Array#includes vous pouvez utiliser la méthode ce polyfill .


Brève explication de la ~ raccourci tilde :

Mise à jour : Puisque nous avons maintenant le includes il n'y a aucun intérêt à utiliser la méthode ~ plus de piratage. Je garde juste ceci ici pour les personnes qui sont intéressées à savoir comment cela fonctionne et/ou qui l'ont rencontré dans le code d'autres personnes.

Au lieu de vérifier si le résultat de indexOf est >= 0 il existe un joli petit raccourci :

if ( ~[1, 2, 3, 4].indexOf(test.type) ) {
    // Do something
}

Voici le violon : http://jsfiddle.net/HYJvK/

Comment cela fonctionne-t-il ? Si un élément est trouvé dans le tableau, indexOf renvoie son index. Si l'élément n'a pas été trouvé, il retournera -1 . Sans trop entrer dans les détails, le ~ es un opérateur NOT par bit qui renverra 0 seulement pour -1 .

J'aime utiliser le ~ car c'est plus succinct que de faire une comparaison sur la valeur de retour. J'aimerais que JavaScript ait une fonction in_array qui renvoie directement un booléen (comme en PHP), mais ce n'est qu'un vœu pieux ( Mise à jour : elle le fait maintenant. Il s'appelle includes . Voir ci-dessus). Notez que la fonction inArray tout en partageant la signature de la méthode PHP, imite en fait la méthode native indexOf (qui est utile dans différents cas, si l'index est ce que vous recherchez vraiment).

Remarque importante : L'utilisation du raccourci tilde semble faire l'objet de controverses, car certains avec véhémence pensent que le code n'est pas assez clair et qu'il faut l'éviter à tout prix (voir les commentaires sur cette réponse). Si vous partagez leur sentiment, vous devriez vous en tenir à l'option .indexOf(...) >= 0 solution.


Une explication un peu plus longue :

Les nombres entiers en JavaScript sont signés, ce qui signifie que le bit le plus à gauche est réservé comme bit de signe ; un drapeau pour indiquer si le nombre est positif ou négatif, avec un symbole 1 être négatif.

Voici quelques exemples de nombres positifs au format binaire 32 bits :

1 :    00000000000000000000000000000001
2 :    00000000000000000000000000000010
3 :    00000000000000000000000000000011
15:    00000000000000000000000000001111

Voici maintenant ces mêmes chiffres, mais en négatif :

-1 :   11111111111111111111111111111111
-2 :   11111111111111111111111111111110
-3 :   11111111111111111111111111111101
-15:   11111111111111111111111111110001

Pourquoi des combinaisons aussi bizarres pour les nombres négatifs ? C'est simple. Un nombre négatif est simplement l'inverse du nombre positif + 1 ; en ajoutant le nombre négatif au nombre positif, on obtient toujours 0 .

Pour comprendre cela, faisons un peu d'arithmétique binaire simple.

Voici comment nous ajouterions -1 a +1 :

   00000000000000000000000000000001      +1
+  11111111111111111111111111111111      -1
-------------------------------------------
=  00000000000000000000000000000000       0

Et voici comment nous ajouterions -15 a +15 :

   00000000000000000000000000001111      +15
+  11111111111111111111111111110001      -15
--------------------------------------------
=  00000000000000000000000000000000        0

Comment obtenir ces résultats ? En faisant des additions régulières, comme on nous l'a appris à l'école : on commence par la colonne la plus à droite et on additionne toutes les lignes. Si la somme est supérieure au plus grand nombre à un chiffre (qui en décimal est 9 mais en binaire, c'est 1 ), nous reportons le reste dans la colonne suivante.

Maintenant, comme vous le remarquerez, lorsqu'on ajoute un nombre négatif à son nombre positif, la colonne la plus à droite qui n'est pas toute 0 auront toujours deux 1 qui, une fois additionnés, donneront 2 . La représentation binaire de deux êtres 10 nous portons le 1 à la colonne suivante, et mettre un 0 pour le résultat de la première colonne. Toutes les autres colonnes à gauche n'ont qu'une seule ligne avec une valeur 1 donc le 1 reporté de la colonne précédente s'élèvera de nouveau à 2 qui se poursuivra ensuite... Ce processus se répète jusqu'à ce que l'on arrive à la colonne la plus à gauche, où les 1 à reporter n'a nulle part où aller, donc il déborde et se perd, et nous nous retrouvons avec 0 de part en part.

Ce système est appelé 2's Complement . Vous pouvez en savoir plus à ce sujet ici :

Représentation du complément à 2 pour les entiers signés .


Maintenant que le cours intensif sur le complément à 2 est terminé, vous remarquerez que -1 est le seul nombre dont la représentation binaire est 1 de tous les côtés.

Utilisation de la ~ Avec l'opérateur NOT, tous les bits d'un nombre donné sont inversés. La seule façon d'obtenir 0 de l'inversion de tous les bits est que si nous avons commencé avec 1 de tous les côtés.

Donc, tout ceci n'était qu'une façon détournée de dire que ~n ne retournera que 0 si n est -1 .

0 votes

Cela ne fait pas la même chose tho

3 votes

@MuhammadUmer - Vous pouvez développer ?

2 votes

Vous pouvez élaborer sur le raccourci tilde.

63voto

Muhammad Umer Points 1964

Utilisation de la science : vous devriez faire ce que idfah a dit et ceci pour la vitesse la plus rapide tout en gardant le code court :

C'EST PLUS RAPIDE QUE ~ Méthode

var x = test.type;
if (x == 'itema' ||
    x == 'itemb' ||
    x == 'itemc' ||
    x == 'itemd') {
    //do something
}

http://jsperf.com/if-statements-test-techsin enter image description here (Ensemble du haut : Chrome, ensemble du bas : Firefox)

Conclusion :

Si les possibilités sont quelques et vous savez que certains d'entre eux sont plus susceptibles de se produire que vous obtenez des performances maximales hors if || , switch fall through et if(obj[keyval]) .

Si les possibilités sont beaucoup de et n'importe lequel d'entre eux pourrait être celui qui se produit le plus souvent, en d'autres termes, vous ne pouvez pas savoir lequel est le plus susceptible de se produire que vous obtenez le plus de performances de la recherche d'objets. if(obj[keyval]) y regex si cela convient.

http://jsperf.com/if-statements-test-techsin/12

Je mettrai à jour si quelque chose de nouveau apparaît.

2 votes

+1 pour un très bon article ! Si je comprends bien, le switch case est la méthode la plus rapide ?

1 votes

Dans firefox oui, dans chrome son if ( ...||...||...)...

0 votes

J'opterais pour ' ||' parce que si quelqu'un est sur chrome, ce qui est le cas de la plupart, il obtiendra la vitesse la plus élevée et s'il est sur ff, il obtiendra quand même beaucoup plus.

32voto

idfah Points 825

Si vous comparez des chaînes de caractères et qu'il existe un modèle, envisagez d'utiliser des expressions régulières.

Sinon, je pense que tenter de le raccourcir ne fera qu'obscurcir votre code. Envisagez de simplement envelopper les lignes pour le rendre plus joli.

if (test.type == 'itema' ||
    test.type == 'itemb' ||
    test.type == 'itemc' ||
    test.type == 'itemd') {
    do something.
}

4 votes

Cette réponse est la gagnante en termes de vitesse jsperf.com/if-statements-test-techsin

1 votes

C'est aussi le plus facile à développer lorsque le projet passe en mode maintenance (avec des règles telles que, (test.type == 'itemf' && foo.mode == 'detailed') )

16voto

kojiro Points 24374
var possibilities = {
  "itema": 1,
  "itemb": 1,
  "itemc": 1,
…};
if (test.type in possibilities) { … }

L'utilisation d'un objet comme tableau associatif est assez courante, mais comme JavaScript ne dispose pas d'un ensemble natif, vous pouvez également utiliser des objets comme des ensembles bon marché.

0 votes

En quoi est-ce plus court que l'instruction if normale que FlyingCat essaie de raccourcir ?

1 votes

@dcarson OP's if La conditionnelle de l'instruction prend 78 caractères si vous supprimez tous les espaces. La mienne en prend 54 si vous l'écrivez comme ceci : test.type in {"itema":1,"itemb":1,"itemc":1,"itemd":1} . Fondamentalement, son utilise quatre caractères pour chaque deux mines utilisées pour chaque clé supplémentaire.

1 votes

Mais vous pouvez faire : if(possibilités[test.type]) et économiser 2 caractères entiers ! :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X