javascript variables coding-style toggle

javascript - ¿Hay una mejor manera de escribir v=(v== 0? 1: 0);



variables coding-style (30)

v = Número (! v)

Se escribirá convertir el valor booleano invertido a número, que es la salida deseada.

Quiero cambiar una variable entre 0 y 1. Si es 0 quiero establecerlo en 1, de lo contrario, si es 1, quiero establecerlo en 0

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

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

¿Puedes mejorar esto?

Edit: la pregunta es cómo escribir la declaración anterior en la menor cantidad de caracteres y al mismo tiempo mantener la claridad. ¿Cómo es esto ''no es una pregunta real''? Esto no pretendía ser un ejercicio de código de golf, aunque se han obtenido algunas respuestas interesantes de personas que se acercan a él como golf, es agradable ver que el golf se utiliza de una manera constructiva y estimulante.


Lista de soluciones

Hay tres soluciones que me gustaría proponer. Todos ellos convierten cualquier valor a 0 (si es 1 , true , etc.) o 1 (si es 0 , false , null , etc.):

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

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

  • v = 1-v

Solución 1

Puedes usar la siguiente solución:

v = 1*!v

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

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

Los resultados son los siguientes:

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

Solucion 2

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

v = +!v

También hace primero el valor booleano desde el valor original, pero usa + lugar de 1* para convertirlo en entero. El resultado es exactamente el mismo, pero la notación es más corta.

Solucion 3

El otro enfoque es utilizar el operador ~~ :

v = ~~!v

Es bastante infrecuente y siempre se convierte en entero desde booleano.


(La honestidad y la integridad matemática, dada la cantidad de votos en esta "respuesta", me han llevado a editar esta respuesta. Me mantuve en suspenso el mayor tiempo posible porque estaba pensado como una breve broma y no como algo "profundo", por lo que fue cualquier explicación parecía contraria al propósito. Sin embargo, los comentarios dejan en claro que debo dejar en 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)

Primero, la confesión: logré confundir mis funciones delta. El delta de Kronecker hubiera 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 funciones delta, debería haber dicho:

v = characteristic_function({0},v)

Déjame aclarar. Recuerde que una función es triple, (X, Y, f) , donde X e Y son conjuntos (llamados dominio y codominio respectivamente) y f es una regla que asigna un elemento de Y a cada elemento de X. A menudo escribimos el 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 de 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 te 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, 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í a funciones delta. Para esto, necesitamos saber acerca de la integración. O ya lo sabes, o no lo sabes. Si no lo hace, nada de lo que pueda decir aquí le dirá acerca de 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 hacer que los promedios funcionen". Es decir, si tenemos un conjunto X y una medida μ en ese conjunto, entonces hay una clase de funciones X → & Ropf; , llamadas funciones medibles para las que 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 los subconjuntos de ese conjunto. Esto se hace asignando a un subconjunto la integral de su función característica (asumiendo que esta es una función medible). Esto puede ser infinito o indefinido (los dos son sutilmente diferentes).

Hay muchas medidas alrededor, 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 aprendes en la escuela (¿se sigue enseñando el 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, es la medida puntual . Se define de modo 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 singleton establecer la medida 1. Esto significa que un subconjunto tiene una medida finita si y solo si es en sí misma finita. Y muy pocas funciones tienen integral finito. Si una función tiene una integral finita, debe ser distinta de cero solo en un número contable de puntos. Por lo tanto, la gran mayoría de las funciones que probablemente conoce no tienen una integral finita bajo esta medida.

Y ahora a funciones delta. Tomemos una definición muy amplia. Tenemos un espacio medible (X, μ) (así que es un conjunto con una medida) y un elemento a ∈ X. "Definimos" la función delta (según a) para que sea la "función" δ a : X → & Ropf; 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 controlarlo es el siguiente: la función delta no necesita ser una función . No está correctamente definido: no he dicho qué es (a (a) .

Lo que hagas en este punto 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. Veamos sus propiedades hipotéticas y veamos si podemos encontrar un hogar adecuado donde esté definido. Podemos hacer eso, y terminamos con distribuciones . Estas no son funciones (necesariamente), 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 los "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 correctamente definida. ¿Quién lo dice? ¿Un grupo de matemáticos? ¡Ingnóralos! ¿Qué saben ellos?

Habiendo ofendido a mi audiencia, continuaré.

El dirac delta generalmente se toma como la función delta de un punto (a menudo 0) en la línea real con su medida estándar. Así que aquellos que se quejan en los comentarios acerca de que yo no sepa que mis deltas lo están haciendo porque están usando esta definición. Para ellos, les pido disculpas: aunque puedo escabullirme usando la defensa del matemático (como lo popularizó Humpty Dumpty : simplemente redefine todo para que sea correcto), es una mala forma usar un término estándar para significar algo diferente.

Pero hay una función delta que hace lo que quiero que haga y es lo que necesito aquí. Si tomo una medida puntual en un conjunto X, entonces hay una función genuina δ a : X → & Ropf; que satisface los criterios para una función delta. Esto se debe a que estamos buscando una función X → & Ropf; que es cero excepto en a y de tal manera que la suma de todos sus valores es 1. Tal función es simple: la única información faltante es su valor en a , y para que la suma sea 1 solo le asignamos el valor valor 1. Esto no es otro que la función característica en {a} . Entonces:

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

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

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 de puntos. 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 no estaba pensando correctamente (no iría tan lejos como para decir que estaba confundido , ya que espero haber demostrado que sé de qué estoy hablando cuando Realmente pienso primero, simplemente no pensé mucho). El significado habitual del delta de dirac no es lo que se busca 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 aspiraba) habría sido la función característica .

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


Dado que 0 es un valor false y 1 es un valor true .

v = (v ? 0 : 1);

Si estás feliz de usar true y false lugar de números

v = !v;

o si deben ser números:

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


Esto falta:

v = [1, 0][v];

Funciona también como 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 ...

O

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

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

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


Las líneas como v = 1 - v , o v ^= 1 o v= +!v harán el trabajo, pero constituyen lo que yo llamaría hacks. Estas no son hermosas líneas de código, sino trucos baratos para lograr el efecto deseado. 1 - v no comunica "cambiar 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 su lugar una función como v = toggle(v) comunica la intención a la vista más rápida.


Lo haría más explícito.

¿Qué significa v ?

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

Implementar 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 cambio de estado se puede hacer creando un nuevo estado basado en el estado actual. Tu sentencia / lógica if se encapsula en tu objeto, que puedes probar. Un valueObject siempre es inmutable, por lo que no tiene identidad. Así que para cambiar su valor tienes que 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);


No sé por qué quieres construir tus propios booleanos? Me gustan las sintaxis funky, 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) es utilizar 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 los booleanos, puedes usar esta sintaxis, que ganará en corto:

v = !v;


Otra forma de hacerlo:

v = ~(v|-v) >>> 31;


Otra forma de su solución original:

v = Number(v == 0);

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


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

  1. Usa una función para el interruptor
  2. Dentro de esta función usar 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 vuelve a leer esto en el futuro, entenderá su código en un tiempo mínimo.

Podrías escribir una función para ella y usarla como:

v = inv(v)


Podrías hacerlo

v = Math.abs(--v);

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


Si debe ser el número entero 1 o 0, entonces la forma en que lo está haciendo está bien, aunque no se necesitan paréntesis. Si estos a son para ser utilizados como booleanos, entonces solo puedes hacer:

v = !v;


Si no te importa 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 utilizar este tipo de enfoque: v será 0 incluso si v es "hola mundo".


Si tiene la garantía de que su entrada es 1 o 0, entonces puede usar:

v = 2+~v;


Simplemente puede utilizar:

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 es más corto pero utiliza 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 utilizar trucos oscuros como los efectos secundarios de los operadores.


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


Una más: v=++v%2

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

PD. Sí, ya sé que se trata de una doble asignación, pero esto es solo una reescritura sin formato del método de C (que no funciona como está, porque el operador de preincremento JS no devuelve el valor l.


define una matriz {1,0}, establece v en v [v], por lo tanto v con un valor de 0 se convierte en 1, y vica versa.


en general, cuando necesite alternar entre dos valores, simplemente 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


v = (v + 1) % 2 y si necesita desplazarse por más valores, simplemente cambie 2 por (n + 1) . Digamos que necesita completar el ciclo 0,1,2 solo v = (v + 1) % 3 .


Bueno, como sabemos, 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/

Espero que esto te ayude :)



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

v = !!v^1;


Si los valores posibles para v son solo 0 y 1, entonces para cualquier entero x, la expresión: v = Math.pow ((Math.pow (x, v) - x), v); cambiará 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


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


Ya que este es JavaScript, podemos usar el unario +para convertir a int:

v = +!v;

Esto hará 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.


v = v == 0 ? 1 : 0;

Es suficiente !


v=!v;

trabajará para v = 0 yv = 1; y alternar el estado;