Existe-t-il une meilleure façon d'écrire v = (v == 0? 1: 0); [fermé]


465

Je veux basculer une variable entre 0 et 1. Si c'est 0 je veux la mettre à 1, sinon si c'est 1 je veux la mettre à 0.

C'est une opération tellement fondamentale que j'écris si souvent que j'aimerais étudier la manière la plus courte et la plus claire possible de le faire. Voici mon meilleur jusqu'à présent:

v = (v == 0 ? 1 : 0);

Pouvez-vous améliorer cela?

Edit: la question est de savoir comment écrire la déclaration ci-dessus dans le moins de caractères tout en conservant la clarté - comment est-ce que «ce n'est pas une vraie question»? Ce n'était pas censé être un exercice de code-golf, bien que des réponses intéressantes soient venues de personnes qui l'approchent comme du golf - c'est agréable de voir le golf utilisé de manière constructive et suscitant la réflexion.


20
Cela me semble déjà simple / clair / court.
Mob

136
ruse:v = +!v;
jAndy

48
Si «mieux» signifie aussi «plus vite»: jsperf.com/v-0-1-0 .
pimvdb

7
@Mobinga: +1. C'est aussi simple que cela devrait l'être. Toutes les autres réponses que je vois sont déroutantes, et certaines changent la logique; l'introduction de bugs.
Ian Boyd

8
@holodoc Une meilleure solution pour exprimer votre opinion serait de créer une réponse qui dit que vous pensez que l'original est la meilleure façon, et d'élaborer pourquoi vous pensez que c'est le cas. cela permet également à d'autres personnes de se rallier facilement à votre réponse en la votant.
Chuck van der Linden

Réponses:


721

Vous pouvez simplement utiliser:

v = 1 - v;

Cela suppose bien sûr que la variable est correctement initialisée, c'est-à-dire qu'elle n'a que la valeur 0 ou 1.

Une autre méthode plus courte mais utilisant un opérateur moins courant:

v ^= 1;

Éditer:

Pour être clair; Je n'ai jamais abordé cette question comme du golf de code, juste pour trouver un moyen court de faire la tâche sans utiliser de trucs obscurs comme les effets secondaires des opérateurs.


206
Ce sont de belles lignes de code, comme du verre finement coupé ou des orchidées à fleurs rares. J'aime la façon dont vous avez atteint directement la couche logique et traité directement les mathématiques de 1 et 0 avec les opérations les plus optimales possibles. Je les utiliserai dans mes propres projets, mais malheureusement, lorsque j'ai besoin que le code soit compris par mes collègues, je devrai adopter par défaut une approche plus logique. Merci cependant, votre réponse a fait ma journée.
Verre Ollie

37
Vous pouvez toujours ajouter un commentaire indiquant ce que fait le code.
Prusse

25
@Kevin: ce n'est pas vrai que cela ne répond clairement pas à la question posée. Le q a dit "Je veux basculer une variable entre 0 et 1." Une interprétation très raisonnable est que cela implique que la valeur de la variable est déjà 0 ou 1. Cette interprétation / limitation a été explicite dans la réponse. À quoi pouvez-vous vous opposer?
LarsH

50
@Matthew pour dire que quelqu'un qui ne trouve pas v ^= 1clair devrait arrêter la programmation est un peu dur je pense. Comme indiqué précédemment, ce n'est pas l'un des opérateurs les plus courants et il ne fait pas la même chose que v = v ^ 1. L'opérateur signifie également quelque chose de complètement différent dans différentes langues (VB). Oui, une recherche rapide vous dira que c'est un opérateur XOR et vous comprendrez ce que cela fait, mais pour beaucoup, cela peut ne pas être évident à première vue. Je ne pense pas que cela signifie que vous devez quitter votre emploi.
JD Isaacks

80
Si vous enregistrez 15 caractères en écrivant ceci mais utilisez ensuite 40 caractères de commentaires pour l'expliquer, est-ce vraiment une amélioration?
Michael Myers

343

Puisque 0est une falsevaleur et 1est une truevaleur.

v = (v ? 0 : 1);

Si vous êtes heureux d'utiliser trueet falseau lieu de chiffres

v = !v;

ou s'ils doivent être des nombres:

v = +!v; /* Boolean invert v then cast back to a Number */

55
mettez juste la magie +avant ça !. Ohhh ça a l'air tellement sale! mais cool: p
jAndy

1
@Quentin - cela cassera le code du gars s'il en a switch(v){ case 0 ...ou si (v == 0) ou si v === 0. Vous modifiez son résultat en plus de son approche ....
Brian

34
Faire un smiley de celui - ci: ({v :+! v}).v.
pimvdb

17
@Brian: pas avec ce +signe magique ! ¯ \ _ (ツ) _ / ¯
jAndy

11
+1 pour v = (v ? 0 : 1)un JS aussi clair et idiomatique.
Bennett McElwee

200

v = (v + 1) % 2et si vous avez besoin de parcourir plusieurs valeurs, changez simplement 2pour (n + 1). Supposons que vous ayez besoin de faire le cycle 0,1,2 v = (v + 1) % 3.


2
J'adore le cycle! C'est vraiment intelligent.
Ollie Glass

16
+1 pour avoir pensé à la bascule comme un cycle. Simple compte tenu de sa flexibilité.
Guffa

3
+1 pour fournir une solution modulaire également robuste. En pratique, vous voudrez probablement utiliser une constvariable à la place des nombres magiques 2, 3, ...
oosterwal

2
Manière plus courte (hackier): ++v % 3si vous voulez parcourir 0, 1, 2
haraldmartin

75

Vous pouvez écrire une fonction pour elle et l'utiliser comme:

v = inv(v)


30
+1 Je suis tout à fait d'accord pour dire que c'est la solution la plus propre (... mais alors ce qui se passe dans la invfonction: P)
Lea Hayes

4
J'aimerais pouvoir donner cette réponse plus que juste +1. Si le code commun n'est pas d'une évidence aveuglante, il doit être encapsulé dans une fonction avec un nom descriptif.
TehShrike

11
@TehShrike considérez-vous comme invun nom descriptif?
Bennett McElwee

3
@Bennett McElwee: inv = inverser. Cela m'a toujours semblé être une abréviation courante.
Daniel

51
Pourquoi l'abréger alors, l'appeler 'inverser' ou 'basculer' et faire en sorte que le code soit lisible. ce n'est pas comme si nous essayions de monter ce genre de choses sur une carte perforée de 80 colonnes ou quelque chose.
Chuck van der Linden

50

Si vous ne vous souciez d'aucune autre possibilité que 1:

v = v ? 0 : 1;

Dans le cas ci-dessus, v finira par être 1 si v est 0, faux, non défini ou nul. Faites attention en utilisant ce type d'approche - v sera 0 même si v est "bonjour le monde".


2
Cela ne renversera pas la valeur. Tu veux dire v = v ? 0 : 1.
Guffa

3
@Guffa - +1 pour avoir attrapé ma dyslexie ...
Brian

3
C'est ma réponse logique préférée que je peux utiliser avec mes collègues (je vois la réponse de @ Guffa comme basée sur les nombres). J'aime la façon dont vous avez pris le test inutile (v == 0) et les crochets, le dépouillant du nombre de caractères minimum absolu. Je vous remercie.
Ollie Glass

1
Je suis aussi un grand fan de la réponse de @ Guffa - selon les mots de Lynn Skynard, restez simple homme;)
Brian

2
+1 pour comprendre les valeurs "véridiques".
zzzzBov

44

Des lignes comme v = 1 - v, ou v ^= 1ou v= +!vferont tout le travail, mais elles constituent ce que j'appellerais des hacks. Ce ne sont pas de belles lignes de code, mais des astuces bon marché pour avoir l'effet escompté. 1 - vne communique pas "basculer la valeur entre 0 et 1". Cela rend votre code moins expressif et introduit un endroit (quoique petit) où un autre développeur devra analyser votre code.

A la place, une fonction telle que v = toggle(v)communique l'intention du premier coup d'œil.


8
-1, sérieusement, v=1-vne communique pas la bascule?
Blindy

22
1-vpeut communiquer en effet basculer, mais c'est que la seule chose qu'il communique. Par exemple, il peut également communiquer une ligne avec zéro à v=1ou une transformation en miroir centrée sur v=0.5. En ce sens, il est relativement ambigu. Il est vrai que le fait de savoir que vcela ne peut qu'être 0ou 1limite sa signification, mais cela oblige les autres développeurs (ou votre futur soi) à comprendre ce contexte avant de pouvoir comprendre cette simple ligne. Vous ne pouvez pas être beaucoup plus clair quev = toggle(v)
Ray

10
v ^= 1est parfaitement clair si vous comprenez les opérations logiques, ce que vous feriez mieux si vous êtes programmeur. Je pense que c'est la différence entre cela et v=1-v; l'une est une opération logique et l'autre une opération arithmétique, et nous essayons de représenter un concept logique et non mathématique.
Matthew Read

6
@Matthew Read: Ceci est une excellente déclaration, qui résume bien mes pensées: "nous essayons de représenter un concept logique et non mathématique." Il a même v ^= 1une certaine ambiguïté, car il peut être interprété comme un bit-xor.
Ray

6
pour les programmeurs (et oui, je veux dire des geeks comme nous), ceux-ci sont assez clairs. Ce ne sont pas des hacks, car ce sont des solutions élégantes en raison de leur simplicité.
gion_13

38

( L'honnêteté et l'intégrité mathématique - étant donné le nombre de votes sur cette "réponse" - m'ont amené à modifier cette réponse. toute explication semblait contraire à l'objectif. Cependant, les commentaires indiquent clairement que je devrais être clair pour éviter tout malentendu. )

Ma réponse originale:

Le libellé de cette partie de la spécification:

Si c'est 0, je veux le mettre à 1, sinon le mettre à 0.

implique que la solution la plus précise est:

v = dirac_delta(0,v)

Tout d' abord, la confession: je ne reçois mes fonctions delta confus. Le delta de Kronecker aurait été légèrement plus approprié, mais pas autant que je voulais quelque chose qui était indépendant du domaine (le delta de Kronecker est principalement utilisé uniquement pour les entiers). Mais je n'aurais vraiment pas dû utiliser les fonctions delta du tout, j'aurais dû dire:

v = characteristic_function({0},v)

Permettez-moi de clarifier. Rappelons que la fonction est une triple, (X, Y, f) , où X et Y sont des ensembles (appelés le domaine et codomaine respectivement) et f est une règle qui attribue un élément de Y à chaque élément de X . Nous écrivons souvent le triple (X, Y, f) comme f: X → Y . Étant donné un sous-ensemble de X , disons A , il existe une fonction caractéristique qui est une fonction χ A : X → {0,1}(il peut également être considéré comme une fonction d'un plus grand codomaine tel que ℕ ou ℝ). Cette fonction est définie par la règle:

χ A (x) = 1 si x ∈ A et χ A (x) = 0 si x ∉ A .

Si vous aimez les tables de vérité, c'est la table de vérité pour la question "L'élément x de X est-il un élément du sous-ensemble A ?".

Donc, d'après cette définition, il est clair que la fonction caractéristique est ce qui est nécessaire ici, avec X un grand ensemble contenant 0 et A = {0} . Voilà ce que j'aurais dû écrire.

Et donc aux fonctions delta. Pour cela, nous devons connaître l'intégration. Soit vous le savez déjà, soit vous ne le savez pas. Si vous ne le faites pas, rien de ce que je peux dire ici ne vous dira les subtilités de la théorie, mais je peux donner un résumé d'une phrase. Une mesure sur un ensemble X est par essence "celle qui est nécessaire pour que les moyennes fonctionnent". C'est-à-dire que si nous avons un ensemble X et une mesure μ sur cet ensemble alors il y a une classe de fonctions X → ℝ , appelées fonctions mesurables pour lesquelles l'expression X f dμ a un sens et est, dans un sens vague, la « moyenne » de f sur X .

Étant donné une mesure sur un ensemble, on peut définir une "mesure" pour des sous-ensembles de cet ensemble. Cela se fait en affectant à un sous-ensemble l'intégrale de sa fonction caractéristique (en supposant qu'il s'agit d'une fonction mesurable). Cela peut être infini ou indéfini (les deux sont subtilement différents).

Il existe de nombreuses mesures, mais deux sont importantes ici. L'un est la mesure standard sur la droite réelle, ℝ. Pour cette mesure, alors f dμ est à peu près ce qu'on vous enseigne à l'école (le calcul est-il toujours enseigné dans les écoles?): Résumez de petits rectangles et prenez des largeurs de plus en plus petites. Dans cette mesure, la mesure d'un intervalle est sa largeur. La mesure d'un point est 0.

Une autre mesure importante, qui fonctionne sur n'importe quel ensemble, est appelée la mesure ponctuelle . Elle est définie de telle sorte que l'intégrale d'une fonction soit la somme de ses valeurs:

X f dμ = ∑ x ∈X f (x)

Cette mesure attribue à chaque ensemble singleton la mesure 1. Cela signifie qu'un sous-ensemble a une mesure finie si et seulement s'il est lui-même fini. Et très peu de fonctions ont une intégrale finie. Si une fonction a une intégrale finie, elle doit être non nulle uniquement sur un nombre dénombrable de points. Ainsi, la grande majorité des fonctions que vous connaissez probablement n'ont pas d'intégrale finie dans le cadre de cette mesure.

Et maintenant aux fonctions delta. Prenons une définition très large. Nous avons un espace mesurable (X, μ) (donc c'est un ensemble avec une mesure sur elle) et un élément a ∈ X . Nous «définissons» la fonction delta (en fonction de a ) comme étant la «fonction» δ a : X → ℝ avec la propriété que δ a (x) = 0 si x ≠ a et X δ a dμ = 1 .

Le fait le plus important à ce sujet est le suivant: La fonction delta n'a pas besoin d'être une fonction . Elle n'est pas correctement définie: je n'ai pas dit ce qu'est δ a (a) .

Ce que vous faites à ce stade dépend de qui vous êtes. Le monde ici se divise en deux catégories. Si vous êtes mathématicien, vous dites ce qui suit:

D'accord, la fonction delta pourrait ne pas être définie. Examinons ses propriétés hypothétiques et voyons si nous pouvons lui trouver un logement approprié là où il est défini. Nous pouvons le faire et nous nous retrouvons avec des distributions . Ce ne sont pas (nécessairement) des fonctions, mais ce sont des choses qui se comportent un peu comme des fonctions, et souvent nous pouvons travailler avec elles comme s'il s'agissait de fonctions; mais il y a certaines choses qu'ils n'ont pas (comme les "valeurs") donc nous devons être prudents.

Si vous n'êtes pas mathématicien, vous dites ce qui suit:

D'accord, la fonction delta n'est peut-être pas correctement définie. Qui le dit? Un tas de mathématiciens? Ignore les! Que savent-ils?

Ayant maintenant offensé mon public, je vais continuer.

Le delta dirac est généralement considéré comme la fonction delta d'un point (souvent 0) dans la ligne réelle avec sa mesure standard. Donc, ceux qui se plaignent dans les commentaires que je ne connais pas mes deltas le font parce qu'ils utilisent cette définition. Pour eux, je m'excuse: bien que je puisse y échapper en utilisant la défense du mathématicien (telle que popularisée par Humpty Dumpty : redéfinissez simplement tout pour que ce soit correct), c'est une mauvaise forme d'utiliser un terme standard pour signifier quelque chose de différent.

Mais il y a une fonction delta qui fait ce que je veux et c'est ce dont j'ai besoin ici. Si je prends une mesure ponctuelle sur un ensemble X alors il y a une véritable fonction δ a : X → ℝ qui satisfait les critères d'une fonction delta. En effet, nous recherchons une fonction X → ℝ qui est nulle sauf en a et telle que la somme de toutes ses valeurs soit 1. Une telle fonction est simple: la seule information manquante est sa valeur en a , et pour que la somme soit 1, il suffit de lui attribuer la valeur 1. Ce n'est autre que la fonction caractéristique sur {a} . Alors:

X δ a dμ = ∑ x ∈ X δ a (x) = δ a (a) = 1.

Donc dans ce cas, pour un ensemble singleton, la fonction caractéristique et la fonction delta s'accordent.

En conclusion, il existe ici trois familles de "fonctions":

  1. Les fonctions caractéristiques des ensembles singleton,
  2. Les fonctions delta,
  3. Les fonctions delta de Kronecker.

Le second d'entre eux est le plus général car l'un des autres en est un exemple lors de l'utilisation de la mesure ponctuelle. Mais le premier et le troisième ont l'avantage d'être toujours de véritables fonctions. Le troisième est en fait un cas particulier du premier, pour une famille particulière de domaines (entiers, ou un sous-ensemble de ceux-ci).

Alors, enfin, quand je l' origine écrit la réponse que je n'étais pas pensé correctement (je n'irais pas jusqu'à dire que je confus , comme je l' espère , je viens démontrais je ne sais de quoi je parle quand En fait, je pense d'abord, je ne pensais pas beaucoup). Le sens habituel du delta dirac n'est pas ce que l'on veut ici, mais l'un des points de ma réponse était que le domaine d'entrée n'était pas défini, de sorte que le delta Kronecker n'aurait pas non plus eu raison. Ainsi, la meilleure réponse mathématique (que je visais) aurait été la fonction caractéristique .

J'espère que tout cela est clair; et j'espère aussi que je n'aurai plus jamais à écrire un morceau mathématique en utilisant des entités HTML au lieu des macros TeX!


37
+1 - Si je pouvais voter contre Quentin pour ne pas connaître la fonction dirac_delta, je le ferais. J'aimerais savoir à quel collège il est allé parce que je ne pense pas que j'embaucherais quelqu'un de là-bas s'il ne sait même pas quelque chose d'aussi fondamental pour le traitement numérique. Je voudrais encore diminuer Quentin pour son incapacité à saisir le peu d'humour que vous tentiez.
Dunk

23
Si je dévalorisais chaque réponse que je ne comprenais pas ... Je dévaloriserais beaucoup de réponses.
Seamus

4
Bonjour Andrew, ça fait un moment.
Tim Down

4
@Tim: Bon deuil, c'est vrai! Et comment va l'évêque des Bermudes? (Est-ce que je m'en souviens bien?) Je suppose que ce fil de commentaires n'est pas le meilleur endroit pour rattraper son retard, cependant ... 17 ans, n'est-ce pas?
Andrew Stacey

3
@ Cԃ ա ԃ "Cette réponse a échoué ..." soupir . Vous avez lu que je suis mathématicien, n'est-ce pas? Cette réponse fonctionne parfaitement pour un programmeur sphérique dans le vide, donc je ne sais pas de quoi vous vous plaignez.
Andrew Stacey

35

Vous pourriez faire

v = Math.abs(--v);

La décrémentation définit la valeur sur 0 ou -1, puis la Math.absconversion -1 sur +1.


27
Cela s'est transformé en un concours «Générer 10000 façons de faire une tâche simple». Et j'aime toutes les façons haha.
Josh

27
v = Math.round(Math.sin(Math.PI/(v+3)));
Benoit

15
@Benoit - votre formule est égale à 1 pour v = 0 et v = 1. CE celui- ci est correcte! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk

2
Cela ne changerait jamais la valeur. Si v = 1alors v = Math.Abs(-1)qui est +1. Si v = 0alors v = Math.Abs(-0)ce qui est 0.
Paul

1
+1 Et c'était mon autre ... Grr.
récursif

34

en général, chaque fois que vous devez basculer entre deux valeurs, vous pouvez simplement soustraire la valeur actuelle de la somme des deux valeurs de basculement:

    0,1 -> v = 1 - v
    1,2 -> v = 3 - v
    4,5 -> v = 9 - v 

2
C'est intéressant et créatif mais potentiellement dangereux. S'il vdevient corrompu, il commencera soudainement à basculer entre deux valeurs différentes. (Juste quelque chose à considérer ...)
oosterwal

1
+1 pour l'idée intéressante. non pas que le PO ou quelqu'un d'autre va réellement l'utiliser dans ces circonstances, mais cette information devrait exister quelque part dans le cerveau pour toujours.
Shimmy Weitzhandler

3
@oosterwal: Alors sûrement, le problème réside dans la corruption ...
GManNickG

@GManNickG: tôt ou tard, la corruption des données se produira, nous devons donc être conscients des conséquences de ne pas les détecter. Si vest normalement utilisé pour exécuter alternativement deux états à partir d'une liste de trois états ou plus, alors une corruption de vpourrait amener le programme à exécuter alternativement deux états complètement différents - cela pourrait entraîner des résultats inattendus et indésirables. La leçon à tirer de ceci est: toujours effectuer des vérifications de plausibilité sur vos données.
oosterwal

33

Si ce doit être l'entier 1 ou 0, alors la façon dont vous le faites est très bien, même si les parenthèses ne sont pas nécessaires. Si ces a doivent être utilisés comme booléens, vous pouvez simplement faire:

v = !v;

10
cela ne résultera-t-il pas dans le "v" d'Ollie à un résultat booléen, pas un entier?
Brian

12
Oui, ce sera le cas, et je l'ai prévenu dans la phrase au-dessus de la ligne de code. Si ces a doivent être utilisés comme booléens
Michael Berkowski

23
v = v == 0 ? 1 : 0;

Est assez !


7
Plus une opinion qu'une réponse, tu ne crois pas?
Brian

16
@Brian: "mieux" est une question d'opinion en fait.
pimvdb

3
J'aime la façon dont vous avez retiré les crochets, ce qui supprime quelques caractères!
Ollie Glass

9
@Brian: La " réponse " est "Non, il n'y a pas de meilleure façon d'écrire v = (v==0 ? 1 : 0);" . Tout le monde trouve différentes façons de jouer au golf; et ne répond pas réellement à la question. C'est pourquoi j'ai voté pour cette réponse.
Ian Boyd

19

Liste des solutions

Il y a trois solutions que je voudrais proposer. Tous les convertir toute valeur 0(si 1, trueetc.) ou 1(si 0, false, nulletc.):

  • v = 1*!v
  • v = +!v
  • v = ~~!v

et un supplémentaire, déjà mentionné, mais intelligent et rapide (bien que ne fonctionne que pour 0s et 1s):

  • v = 1-v

Solution 1

Vous pouvez utiliser la solution suivante:

v = 1*!v

Cela convertira d'abord l'entier en booléen opposé ( 0à Trueet toute autre valeur à False), puis le traitera comme entier lors de la multiplication par 1. En conséquence, 0sera converti en 1et toute autre valeur en 0.

Pour preuve, voyez ce jsfiddle et fournissez toutes les valeurs que vous souhaitez tester: jsfiddle.net/rH3g5/

Les résultats sont les suivants:

  • -123convertira en entier 0,
  • -10convertira en entier 0,
  • -1convertira en entier 0,
  • 0convertira en entier 1,
  • 1convertira en entier 0,
  • 2convertira en entier 0,
  • 60convertira en entier 0,

Solution 2

Comme l'a noté mblase75, jAndy avait une autre solution qui fonctionne comme la mienne:

v = +!v

Il fait aussi d'abord booléen à partir de la valeur d'origine, mais utilise +au lieu de 1*le convertir en entier. Le résultat est exactement le même, mais la notation est plus courte.

Solution 3

Une autre approche consiste à utiliser l' ~~opérateur:

v = ~~!v

Il est assez rare et se convertit toujours en entier de booléen.


En JavaScript, vous pouvez préfixer une variable avec +pour la convertir en un nombre, c'est donc +!véquivalent à votre solution (solution de jAndy dans les commentaires de l'OP).
Blazemonger

@ mblase75: Oui, vous avez raison qui 1*peut être remplacé par +lorsque vous essayez de convertir un booléen en entier. Tout le reste dans ma réponse reste le même. La réponse de jAndy est correcte, mais la mienne est plus détaillée. J'ajouterai sa solution à ma réponse.
Tadeck

@Tadeck +1 pour la bonne idée.
Shimmy Weitzhandler

17

Pour résumer une autre réponse, un commentaire et ma propre opinion, je suggère de combiner deux choses:

  1. Utiliser une fonction pour la bascule
  2. À l'intérieur de cette fonction, utilisez une implémentation plus lisible

Voici la fonction que vous pourriez placer dans une bibliothèque ou peut-être envelopper dans un plugin pour un autre Framework Javascript.

function inv(i) {
  if (i == 0) {
    return 1
  } else {
    return 0;
  }
}

Et l'utilisation est tout simplement:

v = inv(v);

Les avantages sont:

  1. Pas de duplication de code
  2. Si vous ou quelqu'un lisez à nouveau ceci à l'avenir, vous comprendrez votre code en un minimum de temps.

Sont-ils? J'ai effectué un test rapide: jsperf.com/function-vs-no-function/2 et il semble que la différence n'est pas si grande.
Martin Schlagnitweit

25
7,5 ns contre 8,8 ns. Ces 1,3 nanosecondes supplémentaires vous tueront vraiment.
Ian Boyd

5
Avec tout le temps que j'ai économisé, j'ai emmené ma famille à Disney World! :-)
Tom

1
Tout à fait correct. Les personnes qui écrivent des solutions «intelligentes» n'ont probablement jamais eu à maintenir le code des «gemmes» des autres programmeurs
Avi

1
pourquoi pas function toggle(i){ return i == 0 ? 1 : 0 }?
Billy Moon

13

Je ne sais pas pourquoi tu veux construire tes propres booléens? J'aime les syntaxes funky, mais pourquoi ne pas écrire du code compréhensible?

Ce n'est pas le plus court / le plus rapide, mais le plus clair (et lisible pour tout le monde) utilise l'état if / else bien connu:

if (v === 0)
{
  v = 1;
}
else
{
  v = 0;
}

Si vous voulez être vraiment clair, vous devez utiliser des booléens au lieu de chiffres pour cela. Ils sont assez rapides pour la plupart des cas. Avec les booléens, vous pouvez simplement utiliser cette syntaxe, qui gagnera en brièveté:

v = !v;

1
Ce serait en fait ma réponse préférée; mais l' opérateur ternaire vs if-else est une guerre sainte sur laquelle je ne voulais pas allumer le fusible. Cela dit, je pense que la première ligne devrait être === 0. Avec un échantillon d'entrée de 7, la sortie correcte est 0, mais cela sortira 1.
Ian Boyd

4
Est-il utile de corriger silencieusement une entrée comme 7 au lieu de lever une exception quelconque? Je veux dire, si un autre morceau de code a les mains sur le 7 alors qu'il attendait 0 ou 1 seulement, avant que votre code ne corrige la valeur?
Chuck van der Linden

12

Une autre forme de votre solution originale:

v = Number(v == 0);

EDIT: Merci TehShrike et Guffa pour avoir signalé l'erreur dans ma solution d'origine.


4
L'opérateur == renvoie un booléen (au lieu d'un entier) sous de nombreux systèmes. Cela ne fonctionnerait que si v était défini comme un entier et que le langage était cool avec une conversion automatique de booléen en entier.
TehShrike

Très vrai. Je répondais à la question dans le contexte de javascript (comment la question a été balisée).
Kurt Kaylor

@Kurt Kaylor: Javascript est l'un des systèmes où l'opérateur == renvoie un booléen, il ne fait donc pas la même chose que la solution d'origine.
Guffa

@Guffa: Je profite du fait que javascript est un langage faiblement typé avec une conversion de type implicite (par exemple '0.0000 '== 0, 0 == "", false == "", false == 0, 1 == vrai, etc.). Je peux utiliser la valeur booléenne retournée de la même manière que je peux utiliser un entier de valeur 0 ou 1. Essayez, par exemple, d'évaluer "2 + true" dans une console javascript, vous obtiendrez 3.
Kurt Kaylor

1
@Kurt Kaylor: Cela ne fonctionne que dans les situations où vous forcez une conversion implicite. Essayez par exemple 'opacity:'+trueet vous vous retrouvez avec opacity:trueau lieu de opacity:1.
Guffa

11

Je voudrais le rendre plus explicite.

Que veut vdire?

Par exemple, lorsque v est un état. Créez un statut d'objet. En DDD, un objet de valeur.

Implémentez la logique dans cet objet de valeur. Ensuite, vous pouvez écrire votre code d'une manière plus fonctionnelle et plus lisible. Le changement d'état peut être effectué en créant un nouvel état basé sur l'état actuel. Votre instruction / logique if est ensuite encapsulée dans votre objet, que vous pouvez annuler. Un valueObject est toujours immuable, il n'a donc pas d'identité. Donc, pour changer sa valeur, vous devez en créer une nouvelle.

Exemple:

public class Status
{
    private readonly int _actualValue;
    public Status(int value)
    {
        _actualValue = value;
    }
    public Status(Status status)
    {
        _actualValue = status._actualValue == 0 ? 1 : 0; 
    }

    //some equals method to compare two Status objects
}

var status = new Status(0);

Status = new Status(status);

6
sur l'ingénierie?
alejandro5042

6
+1 pour m'avoir fait rire
Denshi


10

Cela manque:

v = [1, 0][v];

Cela fonctionne aussi comme round robin:

v = [2, 0, 1][v]; // 0 2 1 0 ...
v = [1, 2, 0][v]; // 0 1 2 0 ...
v = [1, 2, 3, 4, 5, 0][v]; // 0 1 2 3 4 5 ...
v = [5, 0, 1, 2, 3, 4][v]; // 0 5 4 3 2 1 0 ...

Ou

v = {0: 1, 1: 0}[v];

Le charme de la dernière solution, il fonctionne également avec toutes les autres valeurs.

v = {777: 'seven', 'seven': 777}[v];

Pour un cas très spécial, comme obtenir une valeur (changeante) et undefined, ce modèle peut être utile:

v = { undefined: someValue }[v]; // undefined someValue undefined someValue undefined ...

9

Comme il s'agit de JavaScript, nous pouvons utiliser l'unaire +pour convertir en int:

v = +!v;

Cela va logiquement NOTla valeur de v(donnant truesi v == 0ou falsesi v == 1). Ensuite, nous convertissons la valeur booléenne retournée en sa représentation entière correspondante.


8

Juste pour les coups de pied: v = Math.pow(v-1,v)bascule également entre 1 et 0.


7

Un de plus: v=++v%2

(en C ce serait simple ++v%=2)

ps. Oui, je sais que c'est une double affectation, mais ce n'est qu'une réécriture brute de la méthode de C (qui ne fonctionne pas en l'état, car l'opérateur de pré-incrémentation JS ne renvoie pas lvalue.


3
Votre version C est illégale; vous ne pouvez pas modifier le résultat d'un ++opérateur (ce n'est pas une valeur l). Quant à v=++v%2, vous modifiez vdeux fois. Je ne sais pas si c'est bien défini en JavaScript, mais ce n'est pas nécessaire. v = (v+1) % 2.
Keith Thompson

Au moins, c++c'est parce que l'opérateur de pré-incrémentation a une priorité plus élevée et modifie la variable «en place», de sorte qu'elle peut être utilisée comme valeur l. Je pense que l'implémentation de JS ++est telle qu'elle ne peut pas être traitée comme une valeur l: / Et oui, c'est redondant, mais j'essayais de montrer juste une autre méthode - il y a déjà de meilleures solutions publiées :)
Adam Jurczyk

3
+1. Peut être écrit comme v = (v + 1)% 2.
niktrs

7

Si vous êtes assuré que votre entrée est soit 1 soit 0, alors vous pouvez utiliser:

v = 2+~v;

7

définir un tableau {1,0}, définir v sur v [v], donc v avec une valeur de 0 devient 1, et vice versa.


Ma solution est correcte, si vous ne l'aimez pas, écrivez pourquoi. Votre commentaire n'aide personne. Ma solution lit une variable, au lieu de prendre une décision. Cela nécessite moins de CPU.
S ..

5

Une autre façon créative de le faire, en vétant égale à n'importe quelle valeur, reviendra toujours 0ou1

v = !!v^1;

3
deux !!résultent en rien en maths logiques, vous pouvez !!!!y entrer et seront les mêmes mais il en résultera 4 opérations inutiles
Alex K

10
@Alex: !!jettera à un bool. !!(1) === trueet!!(0) === false
nickf

1
@nickf: aha, donc je suppose que ce v = Boolean(v^1)serait plus informatif, merci pour l'explication - je n'ai pas pensé au casting
Alex K

1
@Alex, "mathématiques logiques"? C'est pourquoi les mathématiciens sont de mauvais programmeurs. Ne vous méprenez pas; les bons programmeurs sont également bons pour comprendre les mathématiques. Mais cela n'a rien à voir avec les mathématiques logiques. C'est une construction de langage qui, quelle que soit l'expression, au moins en Javascript, !la transforme en booléen. Ajouter un autre !annulera ce booléen. Le casting est implicite ici, et le résultat final fonctionne. Il n'y a pas besoin de -1.
Yanick Rochon

1
je ne suis pas du tout mathématicien. vous pouvez essayer cela et vous voir jsperf.com/javascript-boolean-test
Alex K

4

Si les valeurs possibles pour v ne sont que 0 et 1, alors pour tout entier x, l'expression: v = Math.pow ((Math.pow (x, v) - x), v); fera basculer la valeur.

Je sais que c'est une solution laide et l'OP ne le cherchait pas ... mais je pensais à une autre solution quand j'étais dans les toilettes: P



3
v=!v;

fonctionnera pour v = 0 et v = 1; et basculer l'état;


1

S'il n'y a que deux valeurs, comme dans ce cas (0, 1), je pense qu'il est inutile d'utiliser int. Optez plutôt pour le booléen et travaillez en morceaux. Je sais que je suppose, mais en cas de basculement entre deux états, le booléen semble être le choix idéal.


1

Eh bien, comme nous le savons, en javascript, seule cette comparaison booléenne vous donnera également le résultat attendu.

c'est à dire v = v == 0suffit pour cela.

Voici le code pour cela:

var v = 0;
alert("if v  is 0 output: " + (v == 0));

setTimeout(function() {
  v = 1;
  alert("if v  is 1 Output: " + (v == 0));
}, 1000);

JSFiddle: https://jsfiddle.net/vikash2402/83zf2zz0/

En espérant que cela vous aidera :)


Cela fonctionne pour basculer une valeur, mais la valeur ne bascule pas entre 0 et 1, mais plutôt entre trueet false. Vous pouvez utiliser v == 0pour déterminer la valeur de la variable dans une condition, mais si vous souhaitez utiliser la valeur 0 ou 1, vous devez utiliser quelque chose comme v == 0 ? 0 : 1ou Number(v)pour l'obtenir. (En outre, vous pouvez utiliser v = !v;pour basculer entre trueet false.)
Guffa

ouais je l'ai .. merci :)
Vikash Pandey

0

v = nombre (! v)

Il tapera la valeur booléenne inversée en nombre, qui est la sortie souhaitée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.