2010-07-20 26 views
16

Parece que manejo casos especiales como este con cierta frecuencia. Tiene que ser una sintaxis más concisa o construir:¿Hay alguna forma más sencilla de hacer esto?

var x = solveForX(); /* some slow calculation here */ 
if (x < 0) 
{ 
    x = 0; 
} 

Esto es equivalente, pero no se siente más elegante:

var x; 
x = (x = solveForX()) < 0 ? 0 : x; 

Tal vez hay un truco desplazamiento de bits?


Actualización: me corrieron some benchmarks comparar mis dos respuestas favoritas - el que acepté, y Peter Ajtai's. ¡Resulta que Peter es bastante más rápido! Ejecutar 1,000,000 de iteraciones de cada uno (también ejecuté una versión que almacena en caché Math.max para ver cuánto tiempo contribuyó la búsqueda) muestra que Peter se ejecuta en menos de la mitad del tiempo de la versión Math.max, incluso con el almacenamiento en caché max.

Dicho esto, incluso el método "más lento" sigue siendo bastante rápido.

+0

¿Por qué no actualizar solveForX para devolver 0 cuando es negativo? – Fosco

+1

¡Creo que debería funcionar bien! –

+1

@Fosco - Tal vez es una función genérica, y este es un caso especial –

Respuesta

29

¿Qué tal

var x = Math.max(solveForX(), 0); 
+0

Este es * el * camino –

+6

FWIW, aunque esto es más escueto, como un lector de código, esta forma me toma varios segundos más analizar que la forma original del OP. –

+3

No es la cosa más clara, usando 'Math.max' para implementar un mínimo –

10

Algo así como:

x = Math.max(0, solveForX()); 
+0

Esta es * la * forma. –

8
(x < 0) && (x = 0); 

Editar: Se ha eliminado la sentencia if. Gracias Andreas.

Esta es una línea, y está claro lo que hace (en mi opinión personal) - si está familiarizado con la evaluación de corto circuito booleano.

Lo anterior hace uso de boolean short circuit evaluation. Esto puede ser muy útil en ciertas situaciones (especialmente la aritmética del puntero en C++, pero la evaluación del cortocircuito booleano también funciona en Javascript).

x = 0 solo evalúa si x < 0.

He aquí dos ejemplos:

Esto alerta 1:

<script type="text/javascript"> 
    var x = 1; 
    (x < 0) && (x = 0); 
    alert(x); 
</script> 

Esto alerta: 0

<script type="text/javascript"> 
    var x = -1; 
    (x < 0) && (x = 0); 
    alert(x); 
</script> 
+0

¡Ver eso hizo que me dolieran los ojos! –

+2

x = 0 siempre asignará nunca evaluar – Woot4Moo

+0

ghostrider negativo – Woot4Moo

2

me gustaría decorar la función original solveForX.

function returnNonNegative(fn) { 
    function _f() { 
     var x = fn(); 
     if (x < 0) { 
      x = 0; 
     } 
     return x; 
    } 
    return _f; 
} 

solveForX = returnNonNegative(solveForX); 

En este caso particular, el uso de Math.max parece estar bien, pero este patrón proporciona una solución genérica para este tipo de problemas.

+1

Creo que esta pregunta es sobre '' x = (x = solveForX()) <0? 0: x; 'declaración por sí mismo, no sobre la función' solveForX' o el contexto del OP. –

+0

@Andreas Rejbrand: la pregunta era "¿hay alguna manera más astuta" de escribir el constructo anterior que consista en una llamada de función y algún comportamiento adicional? Creo que este es el caso típico para el patrón decorador. La sintaxis se puede mejorar de varias maneras, pero esto hace que la semántica sea más clara. –

0

La respuesta aceptada es perfecta.Si usted quiere lograr lo mismo sin una llamada de función, creo que esto es lo más concisa:

var x; 
(x = solveForX()) > 0 || (x = 0); 

(En Safari, esta implementación es un conjunto 7% más rápido que Math.max(), que es probablemente no vale la pena preocuparse)

+0

Math.max (más allá, thunderdome) tiene mejores escenas de lucha. – Matt

+0

'var Mad = Math; var x = Mad.max (más allá, thunderdome); 'FTFY –

0

¡Creo que esta manera es muy bonita!

var x = Math.max(solveForX(), 0); 

Buena suerte!

+0

Lo sentimos, pero esta respuesta ya se ha publicado varias veces. ¿Qué significa esto? –

Cuestiones relacionadas