web-dev-qa-db-fra.com

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

Je souhaite basculer une variable entre 0 et 1. Si c'est 0, je veux la définir sur 1, sinon si elle est 1, je veux la définir sur 0.

C’est une opération tellement fondamentale que j’écris si souvent que j’aimerais étudier le moyen le plus court et le plus clair de le faire. Voici mon meilleur jusqu'ici:

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

Pouvez-vous améliorer cela?

Edit: la question est de savoir comment écrire la déclaration ci-dessus avec le moins de caractères possible tout en conservant la clarté. Comment est-ce que cette "question n'est pas réelle"? Ce n’était pas censé être un exercice de code-golf, bien que des réponses intéressantes aient été fournies par des personnes qui l’appelaient golf: il est agréable de voir le golf utilisé de manière constructive et stimulante.

450
Ollie Glass

Vous pouvez simplement utiliser:

v = 1 - v;

Bien entendu, cela suppose 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 qui utilise un opérateur moins commun:

v ^= 1;

Modifier:

Pour être clair; Je n'ai jamais abordé cette question sous le nom de code golf, juste pour trouver un moyen court de faire la tâche sans utiliser d'astuces obscurcissantes comme les effets secondaires d'opérateurs.

693
Guffa

Puisque 0 est une valeur false et 1 est une valeur true.

v = (v ? 0 : 1);

Si vous préférez utiliser true et false au lieu de nombres

v = !v;

ou s'ils doivent être des nombres:

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

v = (v + 1) % 2 et si vous devez parcourir plusieurs valeurs, changez simplement 2 pour (n + 1). Supposons que vous deviez faire un cycle 0,1,2, faites simplement v = (v + 1) % 3.

199
Prusse

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

v = inv(v)

75
Daniel

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

v = v ? 0 : 1;

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

50
Brian

Des lignes telles que v = 1 - v, ou v ^= 1 ou v= +!v feront tout le travail, mais elles constituent ce que je qualifierais de hacks. Ce ne sont pas de belles lignes de code, mais des astuces peu coûteuses pour avoir l'effet escompté. 1 - v ne communique pas "bascule la valeur entre 0 et 1". Cela rend votre code moins expressif et introduit un endroit (bien que petit) où un autre développeur devra analyser votre code.

Avoir à la place une fonction comme v = toggle(v) communique l'intention au premier coup d'œil.

44
Ray

( 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. Je me suis abstenue aussi longtemps que possible, car elle était conçue comme un petit bout pas quelque chose de "profond", donc ajouter des explications semblait aller à l’encontre du but recherché. Cependant, les commentaires indiquent clairement que je devrais être clair pour éviter tout malentendu. )

Ma réponse initiale:

Le libellé de cette partie du cahier des charges:

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)

Premièrement, la confession: Je ai confond mes fonctions delta. Le delta de Kronecker aurait été légèrement plus approprié, mais pas beaucoup car je voulais quelque chose qui soit 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, j’aurais dû dire:

v = characteristic_function({0},v)

Laissez-moi clarifier. Rappelons qu'une fonction est un 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 assigne 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 est une fonction caractéristique qui est une fonction UNE: X → {0,1} (il peut également être considéré comme une fonction d'un domaine de code plus grand, tel que ou). Cette fonction est définie par la règle:

χUNE(x) = 1 si x ∈ A et UNE(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 un élément du sous-ensemble A? ".

Donc, de 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} . C'est ce que j'aurais écrit .

Et ainsi aux fonctions delta. Pour cela, nous devons connaître l'intégration. Ou vous le savez déjà, ou vous ne le savez pas. Si vous ne le faites pas, je ne peux rien dire ici qui puisse vous parler de la complexité de la théorie, mais je peux vous résumer une phrase. Une mesure sur un ensemble X est en substance "ce 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, il existe une classe de fonctions X → , appelées fonctions mesurables pour lequel l'expression X f dμ est logique et correspond, 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. Ceci est fait en affectant à un sous-ensemble l'intégrale de sa fonction caractéristique (en supposant qu'il s'agisse d'une fonction mesurable). Ceci peut être infini ou indéfini (les deux sont légèrement différents).

Il y a beaucoup de mesures, mais il y en a deux qui sont importantes ici. L'un est la mesure standard sur la ligne réelle,. Pour cette mesure, alors  f dμ est à peu près ce que l’on vous enseigne à l’école (le calcul est-il encore enseigné à l’école?): résumez des 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 tout ensemble , est appelée la mesure de point . Il est défini pour que l'intégrale d'une fonction soit la somme de ses valeurs:

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

Cette mesure affecte à chaque singleton la mesure 1. Cela signifie qu'un sous-ensemble a une mesure finie si et seulement si elle est elle-même finie. 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 de points dénombrable . Ainsi, la grande majorité des fonctions que vous connaissez probablement ne possèdent pas une intégrale finie dans cette mesure.

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

Le fait le plus important à ce sujet est le suivant: La fonction delta ne doit pas nécessairement être une fonction. C'est pas correctement défini: je n'ai pas dit quoi δune(a) est.

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

Ok, donc la fonction delta peut ne pas être définie. Examinons ses propriétés hypothétiques et voyons si nous pouvons trouver une maison appropriée où elle est définie. Nous pouvons le faire et nous nous retrouvons avec des distributions . Ce sont non pas (nécessairement) des fonctions, mais ce sont des choses qui se comportent un peu comme des fonctions, et nous pouvons souvent les utiliser comme si elles étaient des fonctions; mais il y a certaines choses qu'ils n'ont pas (telles que les "valeurs"), nous devons donc faire attention.

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

Ok, donc la fonction delta peut ne pas être définie correctement. Qui le dit? Un groupe de mathématiciens? Ignore les! Que savent-ils?

Ayant maintenant offensé mon public, je vais continuer.

Le dirac delta est généralement considéré comme la fonction delta d'un point (souvent 0) dans la droite réelle avec sa mesure standard. Donc, ceux qui se plaignent dans les commentaires à propos de moi sans savoir que mes deltas le font parce qu'ils utilisent cette définition. Pour eux, je m'excuse: bien que je puisse m'en sortir en utilisant la défense du mathématicien (popularisée par Humpty Dumpty : redéfinissez simplement tout pour qu’il soit correct), il est mauvais d’utiliser un terme standard pour désigner 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 de point sur un ensemble X, il est une fonction authentique δune : X → ℝ qui satisfait aux critères d'une fonction delta. En effet, nous recherchons une fonction X → qui est égale à zéro sauf à a et telle que la somme de toutes ses valeurs est 1. Une telle fonction est simple: la seule information manquante est sa valeur à a , et pour que la somme soit égale à 1, il suffit de lui attribuer la valeur 1. Ce n'est autre que la fonction caractéristique sur {a} . Ensuite:

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

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

En conclusion, il y a trois familles de "fonctions" ici:

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

Le deuxième de ces derniers est le plus général, car aucun des autres n'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 de domaines particulière (entiers, ou un sous-ensemble de ceux-ci).

Donc, finalement, quand j’ai écrit la réponse, j’étais ( pas bien en train de penser correctement (je n’irais pas jusqu’à dire que j’étais confus , comme j'espère que je viens de démontrer que je fais je sais ce que je ' je parle de la première fois où je pense, je ne pensais tout simplement pas beaucoup). Le sens habituel du delta dirac n’est pas ce qui est voulu ici, mais l’un des points de ma réponse était que le domaine en entrée était et non , de sorte que le Kronecker delta n'aurait pas eu raison non plus. Ainsi, la meilleure réponse mathématique (que je visais) aurait été la fonction caractéristique.

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

39
Loop Space

Vous pourriez faire 

v = Math.abs(--v);

La décrémentation définit la valeur sur 0 ou -1, puis le Math.abs convertit -1 en +1.

35
Paul

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:

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

S'il doit s'agir du nombre entier 1 ou 0, la procédure est correcte, bien que les parenthèses ne soient pas nécessaires. Si ceux-ci doivent être utilisés comme booléens, vous pouvez simplement faire:

v = !v;
33
Michael Berkowski
v = v == 0 ? 1 : 0;

Est assez !

23
nidhin

Liste de solutions

Il y a trois solutions que je voudrais proposer. Tous convertissent n'importe quelle valeur en 0 (si 1, true etc.) ou 1 (si 0, false, null etc.):

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

et un autre, 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 le booléen opposé (0 en True et toute autre valeur en False), puis le traitera comme un entier lors de la multiplication par 1. En conséquence, 0 sera converti en 1 et toute autre valeur en 0.

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

Les résultats sont les suivants:

  • -123 sera converti en entier 0,
  • -10 sera converti en entier 0,
  • -1 sera converti en entier 0,
  • 0 sera converti en entier 1,
  • 1 sera converti en entier 0,
  • 2 sera converti en entier 0,
  • 60 sera converti en entier 0,

Solution 2

Comme le note mblase75, jAndy avait une autre solution qui fonctionne comme la mienne:

v = +!v

Il commence aussi par créer un booléen à partir de la valeur d'origine, mais utilise + au lieu de 1* pour la 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

C'est assez rare et convertit toujours en entier de booléen.

18
Tadeck

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. Dans cette fonction, utilisez une implémentation plus lisible.

Voici la fonction que vous pourriez placer dans une bibliothèque ou éventuellement envelopper dans un plugin pour un autre framework Javascript.

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

Et l'utilisation est simplement:

v = inv(v);

Les avantages sont:

  1. Pas de duplication de code
  2. Si vous, ou quiconque, lisez ceci à l'avenir, vous comprendrez votre code dans un minimum de temps.
17

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 par tout le monde) utilise l'état bien connu if/else:

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

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

v = !v;
13
Mark Knol

Une autre forme de votre solution originale:

v = Number(v == 0);

EDIT: Merci à TehShrike et Guffa d’avoir signalé l’erreur dans ma solution initiale.

12
Kurt Kaylor

Je le rendrais plus explicite.

Que signifie v?

Par exemple, lorsque v est un état. Créer un objet Statut. Dans DDD un objet de valeur.

Implémentez la logique dans cet objet de valeur. Ensuite, vous pouvez écrire votre code de manière plus fonctionnelle, plus lisible. Le changement d'état peut être effectué en créant un nouvel état basé sur l'état actuel. Votre déclaration/logique if est ensuite encapsulée dans votre objet, ce que vous pouvez désactiver. Un valueObject est toujours immuable, il n'a donc aucune 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);
11
Marco Franssen

C'est manquant:

v = [1, 0][v];

Cela fonctionne aussi bien en 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, cela fonctionne aussi avec toutes les autres valeurs.

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

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

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

Une autre façon de le faire:

v = ~(v|-v) >>> 31;
10
Eng.Fouad

Juste pour le plaisir: v = Math.pow(v-1,v) bascule également entre 1 et 0.

8
Blazemonger

Un de plus: v=++v%2

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

ps. Oui, je sais que c'est une double tâche, mais il s'agit simplement d'une réécriture brute de la méthode de C (qui ne fonctionne pas telle quelle, car l'opérateur de pré-incrémentation JS ne renvoie pas la valeur lvalue.

7
Adam Jurczyk

définissez un tableau {1,0}, définissez v sur v [v], donc v avec une valeur de 0 devient 1 et vica inversement.

7
S..

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

v = 2+~v;
7
brandx

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

v = +!v;

Ceci va logiquement NOT la valeur de v (donnant true si v == 0 ou false si v == 1). Ensuite, nous convertissons la valeur booléenne renvoyée dans sa représentation entière correspondante.

6
0x499602D2

Une autre façon créative de le faire, avec v étant égal à une valeur, retournera toujours 0 ou 1

v = !!v^1;
5
Yanick Rochon
v=!v;

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

4
teacher

Si les valeurs possibles pour v ne valent que 0 et 1, l'expression suivante: V = Math.pow ((Math.pow (x, v) - x), v); Basculera la valeur.

Je sais que c'est une solution laide et que le PO ne cherchait pas cela ... mais je pensais à une autre solution quand j'étais aux toilettes: P

4
Amit

Non testé, mais si vous recherchez un booléen, je pense que var v = !v fonctionnera.

Référence: http://www.jackfranklin.co.uk/blog/2011/05/a-better-way-to-reverse-variables

3
Martin Bean

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

1
Amber

Eh bien, sachant que, dans le javascript, seule la comparaison booléenne vous donnera également le résultat attendu.

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

Ci-dessous 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/

Espérant que cela vous aidera :)

1
Vikash Pandey

v = nombre (! v)

Il va transtyper la valeur booléenne inversée en nombre, ce qui correspond à la sortie souhaitée.

0
Rohit Goyal