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.
javascript
variables
coding-style
toggle
Ollie Glass
fuente
fuente
v = +!v;
Respuestas:
Simplemente puede usar:
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:
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.
fuente
v ^= 1
claro 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 quev = 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.Como
0
es unfalse
valor y1
es untrue
valor.Si está contento de usar
true
y enfalse
lugar de númeroso si deben ser números:
fuente
+
antes de eso!
. Ohhh que se ve muuuuuuuuuuuuuuuuuuuuuuuuuuuu pero genial: pswitch(v){ case 0 ...
o si (v == 0) o si v === 0. Estás cambiando su resultado además de su enfoque ...({v :+! v}).v
.+
signo mágico ! ¯ \ _ (ツ) _ / ¯v = (v ? 0 : 1)
JS tan claro e idiomático.v = (v + 1) % 2
y si necesita recorrer más valores, simplemente cambie2
por(n + 1)
. Digamos que necesitas hacer un ciclo de 0,1,2 solo hazlov = (v + 1) % 3
.fuente
const
variable en lugar de los números mágicos 2, 3, ...++v % 3
si desea recorrer 0, 1, 2Podrías escribir una función para ello y usarlo como:
v = inv(v)
fuente
inv
función: P)inv
que es un nombre descriptivo?Si no le importa ninguna otra posibilidad que no sea 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".
fuente
v = v ? 0 : 1
.Líneas como
v = 1 - v
ov ^= 1
ov= +!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 - v
no 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.fuente
v=1-v
¿no comunica la palanca?1-v
puede comunicarse de hecho alternar, pero eso es lo único que comunica. Por ejemplo, también puede comunicar una línea con cero env=1
, o una transformación de reflejo centrada env=0.5
. En este sentido es relativamente ambiguo. Es cierto que saber esov
solo puede ser0
o1
limitar 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)
v ^= 1
Sin 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 yv=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.v ^= 1
embargo, incluso tiene cierta ambigüedad, ya que puede interpretarse como un bit-xor.(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:
implica que la solución más precisa es:
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:
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:
Si no eres matemático, dices lo siguiente:
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í:
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!
fuente
Podrías hacerlo
La disminución establece el valor en 0 o -1, y luego
Math.abs
convierte -1 en +1.fuente
v = Math.round(Math.sin(Math.PI/(v+3)));
v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));
: Dv = 1
entoncesv = Math.Abs(-1)
cuál es +1. Siv = 0
entoncesv = Math.Abs(-0)
cuál es 0.en general, siempre que necesite alternar entre dos valores, puede restar el valor actual de la suma de los dos valores de alternancia:
fuente
v
se corrompe, de repente comenzará a alternar entre dos valores diferentes. (Solo algo a considerar ...)v
normalmente se usa para ejecutar alternativamente dos estados de una lista de tres o más estados, entonces una corrupciónv
podrí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.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:
fuente
Es suficiente !
fuente
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.Listado de soluciones
Hay tres soluciones que me gustaría proponer. Todos ellos convertir cualquier valor a
0
(si1
,true
etc.), o1
(si0
,false
,null
etc.):v = 1*!v
v = +!v
v = ~~!v
y uno adicional, ya mencionado, pero inteligente y rápido (aunque solo funciona para
0
sy1
s):v = 1-v
Solución 1
Puede usar la siguiente solución:
Esto convertirá primero el entero al booleano opuesto (
0
aTrue
y cualquier otro valor aFalse
), luego lo tratará como entero cuando se multiplique por1
. Como resultado0
, se convertirá a1
y cualquier otro valor a0
.Como prueba, vea este jsfiddle y proporcione los valores que desee probar: jsfiddle.net/rH3g5/
Los resultados son los siguientes:
-123
se convertirá a entero0
,-10
se convertirá a entero0
,-1
se convertirá a entero0
,0
se convertirá a entero1
,1
se convertirá a entero0
,2
se convertirá a entero0
,60
se convertirá a entero0
,Solución 2
Como señaló mblase75, jAndy tenía otra solución que funciona como la mía:
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:Es bastante poco común y siempre se convierte a entero de booleano.
fuente
+
para convertirla en un número, por lo que+!v
es equivalente a su solución (la solución de jAndy en los comentarios del OP).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.Para resumir otra respuesta, un comentario y mi propia opinión, sugiero combinar dos cosas:
Aquí está la función que podría colocar en una biblioteca o tal vez envolverla en un complemento para otro marco de Javascript.
Y el uso es simplemente:
Las ventajas son:
fuente
function toggle(i){ return i == 0 ? 1 : 0 }
?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:
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:
fuente
=== 0
. Con una entrada de muestra de7
, la salida correcta es0
, pero esto dará salida1
.Otra forma de su solución original:
EDITAR: Gracias TehShrike y Guffa por señalar el error en mi solución original.
fuente
'opacity:'+true
y terminas con enopacity:true
lugar deopacity:1
.Lo haría más explícito.
Que
v
significaPor 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:
fuente
Otra forma de hacerlo:
fuente
Esto falta:
Funciona como round robin también:
O
El encanto de la última solución, también funciona con todos los demás valores.
Para un caso muy especial, desea obtener un valor (cambiante) y
undefined
este patrón puede ser útil:fuente
Como se trata de JavaScript, podemos usar el unario
+
para convertir a int:Esto lógico
NOT
el valor dev
(dandotrue
siv == 0
ofalse
siv == 1
). Luego convertimos el valor booleano devuelto en su representación entera correspondiente.fuente
Solo para patadas:
v = Math.pow(v-1,v)
también alterna entre 1 y 0.fuente
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.
fuente
++
operador (no es un valor de l). En cuanto av=++v%2
, estás modificandov
dos veces. No sé si eso está bien definido en JavaScript, pero no es necesario.v = (v+1) % 2
.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 :)Si está garantizado que su entrada es 1 o 0, entonces podría usar:
fuente
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.
fuente
Otra forma creativa de hacerlo, con
v
ser igual a cualquier valor, siempre devolverá0
o1
fuente
!!
dan como resultado nada en matemáticas lógicas, puede poner!!!!
allí y será lo mismo, pero resulta en 4 operaciones innecesarias!!
lanzará a un bool.!!(1) === true
y!!(0) === false
v = Boolean(v^1)
que sería más informativo, gracias por explicar - no pensé en el casting!
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.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
fuente
Sin probar, pero si buscas un booleano, creo
var v = !v
que funcionará.Referencia: http://www.jackfranklin.co.uk/blog/2011/05/a-better-way-to-reverse-variables
fuente
funcionará para v = 0 y v = 1; y alternar el estado;
fuente
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.
fuente
Bueno, como sabemos que en javascript solo esa comparación booleana también le dará el resultado esperado.
v = v == 0
es decir, es suficiente para eso.A continuación se muestra el código para eso:
JSFiddle: https://jsfiddle.net/vikash2402/83zf2zz0/
Esperando que esto te ayude :)
fuente
true
yfalse
. Puede usarv == 0
para determinar el valor de la variable en una condición, pero si desea usar el valor 0 o 1, necesitaría usar algo comov == 0 ? 0 : 1
oNumber(v)
para obtenerlo. (Además, puede usarv = !v;
para alternar entretrue
yfalse
.)Tecleará el valor booleano invertido a Número, que es la salida deseada.
fuente