¿Hay una mejor manera de escribir v = (v == 0? 1: 0); [cerrado]

465

Quiero alternar una variable entre 0 y 1. Si es 0, quiero establecerla en 1; de lo contrario, si es 1, quiero establecerla en 0.

Esta es una operación tan fundamental que escribo tan a menudo que me gustaría investigar la forma más breve y clara posible de hacerlo. Aquí está mi mejor hasta ahora:

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

¿Puedes mejorar esto?

Editar: la pregunta es cómo escribir la declaración anterior en la menor cantidad de caracteres, manteniendo la claridad, ¿cómo es que esta 'no es una pregunta real'? Esto no pretendía ser un ejercicio de código de golf, aunque han surgido algunas respuestas interesantes de personas que lo abordan como golf: es agradable ver que el golf se usa de una manera constructiva y estimulante.

Ollie Glass
fuente
20
Esto ya me parece simple / claro / corto.
Multitud el
136
truco:v = +!v;
jAndy
48
Si 'mejor' también significa 'más rápido': jsperf.com/v-0-1-0 .
pimvdb
77
@Mobinga: +1. Esto es tan simple como debería ser. Todas las otras respuestas que veo son confusas, y algunas de ellas cambian la lógica; introduciendo errores.
Ian Boyd el
8
@holodoc Una mejor solución para expresar tu opinión sería crear una respuesta que diga que crees que el original es la mejor manera, y explicar por qué crees que es así. eso también permite que otras personas se pongan del lado fácilmente de su respuesta al votarla.
Chuck van der Linden

Respuestas:

721

Simplemente puede usar:

v = 1 - v;

Por supuesto, esto supone que la variable se inicializa correctamente, es decir, que solo tiene el valor 0 o 1.

Otro método que es más corto pero usa un operador menos común:

v ^= 1;

Editar:

Para ser claro; Nunca abordé esta pregunta como código de golf, solo para encontrar una forma corta de hacer la tarea sin usar trucos oscuros como los efectos secundarios de los operadores.

Guffa
fuente
206
Estas son hermosas líneas de código, como vidrio finamente cortado o raras orquídeas en flor. Me encanta cómo has llegado directamente a través de la capa lógica y has tratado directamente con las matemáticas de 1 y 0 con las operaciones más óptimas posibles. Los usaré en mis propios proyectos, pero desafortunadamente cuando necesito que el código sea entendido por los compañeros de trabajo, tendré que usar un enfoque más lógico. Sin embargo, gracias, su respuesta me ha alegrado el día.
Ollie Glass el
37
Siempre puede agregar un comentario que indique lo que hace el código.
Prusse
25
@Kevin: no es cierto que esto claramente no responde la pregunta como se le preguntó. La q decía "Quiero alternar una variable entre 0 y 1." Una interpretación muy razonable es que esto implica que el valor de la variable ya es 0 o 1. Esta interpretación / limitación se hizo explícita en la respuesta. ¿A qué demonios puedes objetar?
LarsH
50
@Matthew decir que alguien que no encuentra v ^= 1claro que debe dejar de programar es un poco duro, creo. Como se dijo anteriormente, no es uno de los operadores más comunes y no hace lo mismo que v = v ^ 1. Además, el operador significa algo completamente diferente en diferentes idiomas (VB). Sí, una búsqueda rápida le dirá que es un operador XOR y comprenderá lo que está haciendo, pero para muchos puede no ser obvio a primera vista. No creo que eso signifique que deba renunciar a su trabajo.
JD Isaacks
80
Si guarda 15 caracteres escribiendo esto pero luego usa 40 caracteres de comentarios para explicarlo, ¿es realmente una mejora?
Michael Myers
343

Como 0es un falsevalor y 1es un truevalor.

v = (v ? 0 : 1);

Si está contento de usar truey en falselugar de números

v = !v;

o si deben ser números:

v = +!v; /* Boolean invert v then cast back to a Number */
Quentin
fuente
55
solo pon la magia +antes de eso !. Ohhh que se ve muuuuuuuuuuuuuuuuuuuuuuuuuuuu pero genial: p
jAndy
1
@Quentin: esto romperá el código del chico si tiene switch(v){ case 0 ...o si (v == 0) o si v === 0. Estás cambiando su resultado además de su enfoque ...
Brian
34
Hacer un smiley de la misma: ({v :+! v}).v.
pimvdb
17
@Brian: ¡no con ese +signo mágico ! ¯ \ _ (ツ) _ / ¯
jAndy
11
+1 para v = (v ? 0 : 1)JS tan claro e idiomático.
Bennett McElwee
200

v = (v + 1) % 2y si necesita recorrer más valores, simplemente cambie 2por (n + 1). Digamos que necesitas hacer un ciclo de 0,1,2 solo hazlo v = (v + 1) % 3.

Prusse
fuente
2
¡Amo el ciclo! Eso es realmente inteligente.
Ollie Glass
16
+1 por pensar en la palanca como un ciclo. Simple considerando lo flexible que es.
Guffa
3
+1 por proporcionar una solución modular que también sea robusta. En la práctica, probablemente quieras usar una constvariable en lugar de los números mágicos 2, 3, ...
oosterwal
2
Forma más corta (más pirata): ++v % 3si desea recorrer 0, 1, 2
haraldmartin
75

Podrías escribir una función para ello y usarlo como:

v = inv(v)

Daniel
fuente
30
+1 Estoy totalmente de acuerdo en que esta es la solución más limpia (... pero luego lo que pasa en la invfunción: P)
Lea Hayes
44
Desearía poder dar esta respuesta más que solo +1. Si el código común no es cegadoramente obvio, debe incluirse en una función con un nombre descriptivo.
TehShrike
11
@TehShrike ¿consideras invque es un nombre descriptivo?
Bennett McElwee
3
@Bennett McElwee: inv = invertir. Siempre me pareció una abreviatura común.
Daniel
51
Por qué abreviarlo entonces, llámelo 'invertir' o 'alternar' y haga que el código sea legible. No es como si estuviéramos tratando de encajar estas cosas en una tarjeta perforada de 80 columnas o algo así.
Chuck van der Linden
50

Si no le importa ninguna otra posibilidad que no sea 1:

v = v ? 0 : 1;

En el caso anterior, v terminará siendo 1 si v es 0, falso, indefinido o nulo. Tenga cuidado al usar este tipo de enfoque: v será 0 incluso si v es "hola mundo".

Brian
fuente
2
Eso no cambiará el valor. ¿Quiere decir v = v ? 0 : 1.
Guffa
3
@Guffa - +1 por contraer mi dislexia ...
Brian
3
Esta es mi respuesta basada en lógica favorita que puedo usar con mis compañeros de trabajo (veo la respuesta de @ Guffa como basada en números). Me gusta cómo ha realizado la prueba innecesaria (v == 0) y los corchetes, reduciéndolo al recuento mínimo absoluto de caracteres. Gracias.
Ollie Glass
1
Soy un gran fan de @ respuesta de Guffa también - en palabras de Skynard Lynard, que sea hombre sencillo;)
Brian
2
+1 para comprender los valores de "verdad".
zzzzBov
44

Líneas como v = 1 - vo v ^= 1ov= +!v harán todo el trabajo, pero constituyen lo que yo llamaría hacks. Estas no son hermosas líneas de código, sino trucos baratos para tener el efecto deseado. 1 - vno comunica "alternar el valor entre 0 y 1". Esto hace que su código sea menos expresivo e introduce un lugar (aunque pequeño) donde otro desarrollador tendrá que analizar su código.

Tener en cambio una función como v = toggle(v)comunica la intención a la vista más rápida.

Rayo
fuente
8
-1, en serio, v=1-v¿no comunica la palanca?
Blindy
22
1-vpuede comunicarse de hecho alternar, pero eso es lo único que comunica. Por ejemplo, también puede comunicar una línea con cero en v=1, o una transformación de reflejo centrada en v=0.5. En este sentido es relativamente ambiguo. Es cierto que saber eso vsolo puede ser 0o 1limitar su significado deseado, pero eso obliga a otros desarrolladores (o su futuro yo) a comprender ese contexto antes de poder comprender esta línea simple. No puede ser mucho más claro quev = toggle(v)
Ray
10
v ^= 1Sin embargo, está perfectamente claro si comprende las operaciones lógicas, que sería mejor si fuera un programador. Creo que esa es la diferencia entre eso y v=1-v; uno es una operación lógica y uno es una operación aritmética, y estamos tratando de representar un concepto lógico, no matemático.
Matthew Read
66
@Matthew Read: Esta es una gran declaración, que resume bien mis pensamientos: "estamos tratando de representar un concepto lógico, no matemático". Sin v ^= 1embargo, incluso tiene cierta ambigüedad, ya que puede interpretarse como un bit-xor.
Ray
66
Para los programadores (y sí, quiero decir geeks como nosotros), estos son bastante claros. No son hacks, porque son soluciones elegantes debido a su simplicidad.
gion_13
38

(La honestidad y la integridad matemática, dada la cantidad de votos en esta "respuesta", me han llevado a editar esta respuesta. Espere el mayor tiempo posible porque fue un breve comentario y no como algo "profundo", por lo que poner cualquier explicación parecía contraria al propósito. Sin embargo, los comentarios dejan en claro que debería ser claro para evitar malentendidos. )

Mi respuesta original:

La redacción de esta parte de la especificación:

Si es 0, quiero establecerlo en 1, de lo contrario, establecerlo en 0.

implica que la solución más precisa es:

v = dirac_delta(0,v)

En primer lugar, la confesión: me ponga las funciones delta confundidos. El delta de Kronecker habría sido un poco más apropiado, pero no tanto como quería algo que fuera independiente del dominio (el delta de Kronecker se usa principalmente solo para enteros). Pero realmente no debería haber usado las funciones delta en absoluto, debería haber dicho:

v = characteristic_function({0},v)

Déjame aclarar. Recordemos que un función es un triple, (X, Y, f) , donde X y Y son conjuntos (llamados el dominio y codominio respectivamente) y f es una regla que asigna un elemento de Y a cada elemento de X . Escribimos a menudo la triple (X, Y, f) como f: X → Y . Dado un subconjunto de X , digamos A , hay una función característica que es una función χ A : X → {0,1}(también se puede considerar como una función para un codominio más grande como ℕ o ℝ). Esta función está definida por la regla:

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

Si le gustan las tablas de verdad, es la tabla de verdad para la pregunta "¿Es el elemento x de X un elemento del subconjunto A ?".

Entonces, a partir de esta definición, está claro que la función característica es lo que se necesita aquí, con X un conjunto grande que contiene 0 y A = {0} . Eso es lo que debería haber escrito.

Y así para las funciones delta. Para esto, necesitamos saber sobre la integración. O ya lo sabes o no. Si no lo hace, nada de lo que pueda decir aquí le informará sobre las complejidades de la teoría, pero puedo dar un resumen de una oración. Una medida en un conjunto X es en esencia "lo que se necesita para que los promedios funcionen". Es decir que si tenemos un conjunto X y una medida μ en ese conjunto, entonces hay una clase de funciones X → ℝ , llamadas funciones medibles para las cuales la expresión X f dμ tiene sentido y es, en cierto sentido vago, el "promedio" de f sobre X .

Dada una medida en un conjunto, se puede definir una "medida" para subconjuntos de ese conjunto. Esto se hace asignando a un subconjunto la integral de su función característica (suponiendo que esta sea una función medible). Esto puede ser infinito o indefinido (los dos son sutilmente diferentes).

Hay muchas medidas, pero hay dos que son importantes aquí. Una es la medida estándar en la línea real, ℝ. Para esta medida, entonces f dμ es más o menos lo que se te enseña en la escuela (¿todavía se enseña cálculo en las escuelas?): Resume pequeños rectángulos y toma anchos cada vez más pequeños. En esta medida, la medida de un intervalo es su ancho. La medida de un punto es 0.

Otra medida importante, que funciona en cualquier conjunto, se llama medida puntual . Se define para que la integral de una función sea la suma de sus valores:

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

Esta medida asigna a cada conjunto de singleton la medida 1. Esto significa que un subconjunto tiene una medida finita si y solo si es finita. Y muy pocas funciones tienen integral finita. Si una función tiene una integral finita, debe ser distinta de cero en un número contable de puntos. Entonces, la gran mayoría de las funciones que probablemente conoces no tienen integral finita bajo esta medida.

Y ahora a las funciones delta. Tomemos una definición muy amplia. Tenemos un espacio medible (X, μ) (por lo que es un conjunto con una medida sobre ella) y un elemento a ∈ X . "Definimos" la función delta (dependiendo de a ) para que sea la "función" δ a : X → ℝ con la propiedad de que δ a (x) = 0 si x ≠ a y X δ a dμ = 1 .

El hecho más importante acerca de esto para conseguir esto es: la función delta no necesita ser una función . Se no correctamente definida: no he dicho lo delta un (a) es.

Lo que haces en este momento depende de quién eres. El mundo aquí se divide en dos categorías. Si eres matemático, dices lo siguiente:

Bien, entonces la función delta podría no estar definida. Echemos un vistazo a sus propiedades hipotéticas y ver si podemos encontrar un hogar adecuado para ello donde se define. Podemos hacer eso y terminamos con distribuciones . Estas no son (necesariamente) funciones, pero son cosas que se comportan un poco como funciones, y a menudo podemos trabajar con ellas como si fueran funciones; pero hay ciertas cosas que no tienen (como "valores"), por lo que debemos tener cuidado.

Si no eres matemático, dices lo siguiente:

Bien, entonces la función delta podría no estar definida correctamente. Quien dice eso ¿Un grupo de matemáticos? ¡Ingnóralos! Que saben ellos

Habiendo ofendido ahora a mi audiencia, continuaré.

El delta de dirac generalmente se toma como la función delta de un punto (a menudo 0) en la línea real con su medida estándar. Entonces, aquellos que se quejan en los comentarios sobre mí sin saber mis deltas lo están haciendo porque están usando esta definición. Les pido disculpas: aunque puedo esquivar eso usando la defensa del matemático (como lo popularizó Humpty Dumpty : simplemente redefinir todo para que sea correcto), es una mala forma usar un término estándar para significar algo diferente.

Pero no es una función delta que no hago lo que quiero que haga y es lo que necesito aquí. Si tomo una medida de punto en un conjunto X entonces no es una verdadera función δ un : X → ℝ que satisfaga los criterios para una función delta. Esto se debe a que estamos buscando una función X → ℝ que es cero excepto en una , y de tal manera que la suma de todos sus valores es una función 1. Tal es simple: la pieza única falta de información es su valor en una , y para que la suma sea 1, simplemente le asignamos el valor 1. Esta no es otra que la función característica de {a} . Entonces:

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

Entonces, en este caso, para un conjunto singleton, la función característica y la función delta están de acuerdo.

En conclusión, hay tres familias de "funciones" aquí:

  1. Las funciones características de los conjuntos singleton,
  2. Las funciones delta,
  3. Las funciones delta de Kronecker.

El segundo de estos es el más general, ya que cualquiera de los otros es un ejemplo de ello cuando se usa la medida puntual. Pero el primero y el tercero tienen la ventaja de que siempre son funciones genuinas. El tercero es en realidad un caso especial del primero, para una familia particular de dominios (enteros o algún subconjunto de los mismos).

Así que, finalmente, cuando escribí originalmente la respuesta que yo no estaba pensando correctamente (yo no ir tan lejos como para decir que yo estaba confundido , como espero yo sólo he demostrado que no sé lo que estoy hablando cuando De hecho, primero pienso, simplemente no pensé mucho). El significado habitual del delta de dirac no es lo que se quiere aquí, pero uno de los puntos de mi respuesta fue que el dominio de entrada no estaba definido, por lo que el delta de Kronecker tampoco habría sido correcto. Así, la mejor respuesta matemática (a la que apuntaba) habría sido la función característica .

Espero que todo esté claro; ¡y también espero no tener que volver a escribir una pieza matemática utilizando entidades HTML en lugar de macros TeX!

Andrew Stacey
fuente
37
+1 - Si pudiera denunciar a Quentin por no conocer la función dirac_delta, lo haría. Me gustaría saber a qué universidad asistió porque no creo que contrataría a nadie de allí si ni siquiera saben algo tan fundamental para el procesamiento digital. Quisiera menospreciar a Quentin por su incapacidad para captar el poco de humor que estabas intentando.
Dunk
23
Si rechazara todas las respuestas que no entendía ... rechazaría muchas respuestas.
Seamus
44
Hola Andrew, ha pasado un tiempo.
Tim Down
44
@Tim: ¡Dios mío, así es! ¿Y cómo está el obispo de Bermudas? (¿Lo recuerdo bien?) Supongo que este hilo de comentarios no es el mejor lugar para ponerse al día, aunque ... 17 años, ¿no?
Andrew Stacey
3
@ Cԃ ա ԃ "Esta respuesta ha fallado ..." suspiro . Leíste que soy matemático, ¿no? Esta respuesta funciona perfectamente para un programador esférico en el vacío, así que no sé de qué se queja.
Andrew Stacey
35

Podrías hacerlo

v = Math.abs(--v);

La disminución establece el valor en 0 o -1, y luego Math.absconvierte -1 en +1.

Pablo
fuente
27
Esto se ha convertido en una competencia 'Generar 10000 formas de hacer una tarea simple'. Y me gustan todas las formas jaja.
Josh
27
v = Math.round(Math.sin(Math.PI/(v+3)));
Benoit
15
@Benoit: su fórmula es igual a 1 para v = 0 y v = 1. ¡ESTO es correcto sin embargo! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk
2
Eso nunca cambiaría el valor. Si v = 1entonces v = Math.Abs(-1)cuál es +1. Si v = 0entonces v = Math.Abs(-0)cuál es 0.
Paul
1
+1 Y este fue mi otro ... Grr.
recursivo el
34

en general, siempre que necesite alternar entre dos valores, puede restar el valor actual de la suma de los dos valores de alternancia:

    0,1 -> v = 1 - v
    1,2 -> v = 3 - v
    4,5 -> v = 9 - v 
Mouna Cheikhna
fuente
2
Esto es interesante y creativo pero potencialmente peligroso. Si vse corrompe, de repente comenzará a alternar entre dos valores diferentes. (Solo algo a considerar ...)
oosterwal
1
+1 por la idea interesante. no es que el OP o cualquier otra persona lo vaya a usar en estas circunstancias, pero esta información debería existir en algún lugar del cerebro para siempre.
Shimmy Weitzhandler
3
@oosterwal: Entonces seguramente el problema radica en la corrupción ...
GManNickG
@GManNickG: Tarde o temprano, la corrupción de datos sucederá, por lo que debemos ser conscientes de la consecuencia de no detectarla. Si vnormalmente se usa para ejecutar alternativamente dos estados de una lista de tres o más estados, entonces una corrupción vpodría hacer que el programa ejecute alternativamente dos estados completamente diferentes, lo que podría dar lugar a resultados inesperados e indeseables. La lección que debe extraerse de esto es: Siempre realice verificaciones de plausibilidad en sus datos.
oosterwal
33

Si debe ser el entero 1 o 0, entonces la forma en que lo está haciendo está bien, aunque no se necesitan paréntesis. Si estas se van a utilizar como booleanos, puede hacer lo siguiente:

v = !v;
Michael Berkowski
fuente
10
¿no resultará esto en que la "v" de Ollie se establezca en un resultado booleano, no en un entero?
Brian
12
Sí lo hará, y lo advertí en la oración sobre la línea de código. Si estos son para ser utilizados como booleanos
Michael Berkowski
23
v = v == 0 ? 1 : 0;

Es suficiente !

nidhin
fuente
77
Más de una opinión que una respuesta, ¿no te parece?
Brian
16
@Brian: 'mejor' se trata de opinión en realidad.
pimvdb
3
Me gusta cómo has sacado los corchetes, ¡eso recorta un par de caracteres!
Ollie Glass el
99
@Brian: La " respuesta " es "No, no hay una mejor manera de escribir v = (v==0 ? 1 : 0);" . Todos los demás están encontrando diferentes formas de jugar al golf; y en realidad no responde la pregunta. Es por eso que voté esta respuesta.
Ian Boyd el
19

Listado de soluciones

Hay tres soluciones que me gustaría proponer. Todos ellos convertir cualquier valor a 0(si 1, trueetc.), o 1(si 0, false, nulletc.):

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

y uno adicional, ya mencionado, pero inteligente y rápido (aunque solo funciona para 0sy 1s):

  • v = 1-v

Solución 1

Puede usar la siguiente solución:

v = 1*!v

Esto convertirá primero el entero al booleano opuesto ( 0a Truey cualquier otro valor a False), luego lo tratará como entero cuando se multiplique por 1. Como resultado 0, se convertirá a 1y cualquier otro valor a 0.

Como prueba, vea este jsfiddle y proporcione los valores que desee probar: jsfiddle.net/rH3g5/

Los resultados son los siguientes:

  • -123se convertirá a entero 0,
  • -10se convertirá a entero 0,
  • -1se convertirá a entero 0,
  • 0se convertirá a entero 1,
  • 1se convertirá a entero 0,
  • 2se convertirá a entero 0,
  • 60se convertirá a entero 0,

Solución 2

Como señaló mblase75, jAndy tenía otra solución que funciona como la mía:

v = +!v

También primero hace booleano a partir del valor original, pero usa en +lugar de1* convertirlo en entero. El resultado es exactamente el mismo, pero la notación es más corta.

Solución 3

El otro enfoque es usar el ~~operador:

v = ~~!v

Es bastante poco común y siempre se convierte a entero de booleano.

Tadeck
fuente
En JavaScript, puede prefijar una variable con +para convertirla en un número, por lo que +!ves equivalente a su solución (la solución de jAndy en los comentarios del OP).
Blazemonger
@ mblase75: Sí, tiene razón en que 1*puede reemplazarse +cuando intenta convertir booleano en entero. Todo lo demás en mi respuesta sigue siendo el mismo. La respuesta de jAndy es correcta, pero la mía es más detallada. Agregaré su solución a mi respuesta.
Tadeck
@Tadeck +1 por la buena idea.
Shimmy Weitzhandler
17

Para resumir otra respuesta, un comentario y mi propia opinión, sugiero combinar dos cosas:

  1. Use una función para alternar
  2. Dentro de esta función, use una implementación más legible

Aquí está la función que podría colocar en una biblioteca o tal vez envolverla en un complemento para otro marco de Javascript.

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

Y el uso es simplemente:

v = inv(v);

Las ventajas son:

  1. Sin duplicación de código
  2. Si usted o alguien leen esto nuevamente en el futuro, comprenderán su código en un tiempo mínimo.
Martin Schlagnitweit
fuente
¿Son ellos? Ejecuté una prueba rápida: jsperf.com/function-vs-no-function/2 y parece que la diferencia no es tanta.
Martin Schlagnitweit
25
7.5ns vs 8.8ns. Esos 1.3 nanosegundos adicionales realmente te matarán.
Ian Boyd el
55
¡Con todo el tiempo que ahorré, llevé a mi familia a Disney World! :-)
Tom
1
Totalmente correcto Las personas que escriben soluciones "inteligentes" probablemente nunca tenían que mantener otras "joyas" del código de los programadores
Avi
1
¿por qué no function toggle(i){ return i == 0 ? 1 : 0 }?
Billy Moon
13

No sé por qué quieres construir tus propios booleanos. Me gustan las sintaxis originales, pero ¿por qué no escribir código comprensible?

Este no es el más corto / rápido, pero el más claro (y legible para todos) está utilizando el conocido estado if / else:

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

Si quieres ser realmente claro, debes usar booleanos en lugar de números para esto. Son lo suficientemente rápidos para la mayoría de los casos. Con booleanos, podría usar esta sintaxis, que ganará en breve:

v = !v;
Mark Knol
fuente
1
Esta sería realmente mi respuesta preferida; pero el operador ternario vs if-else es una guerra santa en la que no quería encender el fusible. Dicho esto, creo que la primera línea debería ser === 0. Con una entrada de muestra de 7, la salida correcta es 0, pero esto dará salida 1.
Ian Boyd el
44
¿Hay algún valor en corregir silenciosamente una entrada como 7 en lugar de lanzar una excepción de algún tipo? Quiero decir, ¿qué pasaría si algún otro fragmento de código tuviera en sus manos el 7 cuando esperaba solo 0 o 1, antes de que su código corrigiera el valor?
Chuck van der Linden
12

Otra forma de su solución original:

v = Number(v == 0);

EDITAR: Gracias TehShrike y Guffa por señalar el error en mi solución original.

Kurt Kaylor
fuente
44
El operador == devuelve un valor booleano (en lugar de un número entero) en muchos sistemas. Esto solo funcionaría si v se definiera como un entero, y el lenguaje fuera genial con la conversión automática de booleano a entero.
TehShrike
Muy cierto. Estaba respondiendo la pregunta en el contexto de javascript (cómo se etiquetó la pregunta).
Kurt Kaylor
@Kurt Kaylor: Javascript es uno de los sistemas donde el operador == devuelve un valor booleano, por lo que no hace lo mismo que la solución original.
Guffa
@Guffa: estoy aprovechando el hecho de que JavaScript es un lenguaje débilmente tipado con conversión de tipo implícita (por ejemplo, '0.0000 '== 0, 0 == "", false == "", false == 0, 1 == cierto, etc.). Puedo usar el valor booleano devuelto de la misma manera que puedo usar un entero de valor 0 o 1. Intente, por ejemplo, evaluar "2 + verdadero" en una consola javascript, obtendrá 3.
Kurt Kaylor
1
@Kurt Kaylor: Eso solo funciona en situaciones en las que fuerzas una conversión implícita. Prueba por ejemplo 'opacity:'+truey terminas con en opacity:truelugar de opacity:1.
Guffa
11

Lo haría más explícito.

Que vsignifica

Por ejemplo, cuando v es algún estado. Crear un objeto Estado. En DDD un objeto de valor.

Implemente la lógica en este objeto de valor. Luego puede escribir su código de una manera más funcional que sea más legible. El estado de cambio se puede hacer creando un nuevo Estado basado en el estado actual. Su instrucción / lógica if se encapsula en su objeto, que puede probar unitariamente. Un valueObject siempre es inmutable, por lo que no tiene identidad. Entonces, para cambiar su valor, debe crear uno nuevo.

Ejemplo:

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);
Marco
fuente
66
sobre ingeniería?
alejandro5042
66
+1 por hacerme reír
Denshi
10

Otra forma de hacerlo:

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

Esto falta:

v = [1, 0][v];

Funciona como round robin también:

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 ...

O

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

El encanto de la última solución, también funciona con todos los demás valores.

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

Para un caso muy especial, desea obtener un valor (cambiante) y undefinedeste patrón puede ser útil:

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

Como se trata de JavaScript, podemos usar el unario +para convertir a int:

v = +!v;

Esto lógico NOTel valor de v(dando truesi v == 0o falsesi v == 1). Luego convertimos el valor booleano devuelto en su representación entera correspondiente.

0x499602D2
fuente
8

Solo para patadas: v = Math.pow(v-1,v)también alterna entre 1 y 0.

Blazemonger
fuente
7

Uno mas: v=++v%2

(en C sería simple ++v%=2)

PD. Sí, sé que es una doble asignación, pero esto es solo una reescritura cruda del método de C (que no funciona como es, porque el operador JS previo al incremento no devuelve el valor.

Adam Jurczyk
fuente
3
Su versión C es ilegal; no puede modificar el resultado de un ++operador (no es un valor de l). En cuanto a v=++v%2, estás modificando vdos veces. No sé si eso está bien definido en JavaScript, pero no es necesario. v = (v+1) % 2.
Keith Thompson, el
Al menos en c++esto es, porque el operador de pre-incremento tiene mayor prioridad y modifica la variable 'en el lugar', por lo que puede usarse como lvalue. Creo que la implementación de JS ++es tal que no se puede tratar como un valor: / Y sí, esto es redundante, pero estaba tratando de mostrar solo otro método: ya se han publicado mejores soluciones :)
Adam Jurczyk
3
+1. Se puede escribir como v = (v + 1)% 2.
niktrs
7

Si está garantizado que su entrada es 1 o 0, entonces podría usar:

v = 2+~v;
Brandx
fuente
7

defina una matriz {1,0}, establezca v en v [v], por lo tanto, v con un valor de 0 se convierte en 1 y viceversa.

S ..
fuente
Mi solución es correcta, si no te gusta, escribe por qué. Tu comentario no ayuda a nadie. Mi solución lee una variable, en lugar de tomar una decisión. Esto requiere menos CPU.
S ..
5

Otra forma creativa de hacerlo, con vser igual a cualquier valor, siempre devolverá 0o1

v = !!v^1;
Yanick Rochon
fuente
3
dos no !!dan como resultado nada en matemáticas lógicas, puede poner !!!!allí y será lo mismo, pero resulta en 4 operaciones innecesarias
Alex K
10
@Alex: !!lanzará a un bool. !!(1) === truey!!(0) === false
nickf
1
@nickf: aha, así que supongo v = Boolean(v^1)que sería más informativo, gracias por explicar - no pensé en el casting
Alex K
1
@Alex, "matemáticas lógicas"? Por eso los matemáticos son malos programadores. No me malinterpretes; Los buenos programadores también son buenos para comprender las matemáticas. Pero esto no tiene nada que ver con las matemáticas lógicas. Es una construcción de lenguaje que, dada cualquier expresión, al menos en Javascript, !lo convertirá en booleano. Agregar otro !negará ese booleano. El casting está implícito aquí, y el resultado final funciona. No hay necesidad de -1.
Yanick Rochon
1
No soy matemático en absoluto. puedes probar esto y verte a ti mismo jsperf.com/javascript-boolean-test
Alex K
4

Si los valores posibles para v son solo 0 y 1, entonces para cualquier número entero x, la expresión: v = Math.pow ((Math.pow (x, v) - x), v); alternará el valor.

Sé que esta es una solución fea y el OP no estaba buscando esto ... pero estaba pensando en otra solución cuando estaba en el baño: P

Amit
fuente
3
v=!v;

funcionará para v = 0 y v = 1; y alternar el estado;

profesor
fuente
1

Si solo hay dos valores, como en este caso (0, 1), creo que es un desperdicio usar int. Más bien, elige booleano y trabaja en bits. Sé que estoy asumiendo, pero en caso de alternar entre dos estados, el booleano parece ser la opción ideal.

Ámbar
fuente
1

Bueno, como sabemos que en javascript solo esa comparación booleana también le dará el resultado esperado.

v = v == 0es decir, es suficiente para eso.

A continuación se muestra el código para eso:

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/

Esperando que esto te ayude :)

Vikash Pandey
fuente
Eso funciona para alternar un valor, pero el valor no alterna entre 0 y 1, sino entre truey false. Puede usar v == 0para determinar el valor de la variable en una condición, pero si desea usar el valor 0 o 1, necesitaría usar algo como v == 0 ? 0 : 1o Number(v)para obtenerlo. (Además, puede usar v = !v;para alternar entre truey false.)
Guffa
sí lo tengo ... gracias :)
Vikash Pandey
0

v = Número (! v)

Tecleará el valor booleano invertido a Número, que es la salida deseada.

Rohit Goyal
fuente