2012-05-10 51 views
16

Fui mirando a través del código fuente Raphael.js para averiguar cómo convirtió los valores RGB a HSB. Descubrí la función que lo hizo y yo estaba en el proceso de convertir a Python cuando me encontré con este bonito operador ternario triple anidado:Un operador ternario triple anidado algo doloroso

H = (C == 0 ? null : 
    V == r ? (g - b)/C : 
    V == g ? (b - r)/C + 2 : 
      (r - g)/C + 4 
    ); 

Me lanzó para un bucle porque Python no lo hace tener el mismo tipo de operador ternario que Javascript. Me pasé un tiempo buscando sobre ella y, finalmente, HASHED este código un poco más sano (usando sólo si/else) fuera de él:

if (C == 0) { 
    H = null; 
} else { 
    if(V == r) { 
     H = (g - b)/C; 
    } else { 
     if(V == g) { 
      H = (b - r)/C + 2; 
     } else { 
      H = (r - g)/C + 4; 
     } 
    } 
} 

fue mi interpretación correcta? Solo estoy preguntando esto porque si no es correcto, me enfrento con un lote de depuración. Asi que. ¿Lo "conseguí"?

+0

Sí, parece que tienes la lógica correcta, aparte de un par de discrepancias de capitalización –

+1

la primera 'c' en' if (c == 0) 'debe ser una' c' mayúscula, ¿no? –

+0

¿Eh, verdad? Siento como si hubiera tirado un dardo en un tablero de dardos con mis ciervas atadas a la espalda, con los ojos vendados, y hubiera marcado un tiro al blanco. Y sí, @NiftyDude, eso es correcto. Gracias por la captura! –

Respuesta

20

creo que puede tener esto para evitar la profundidad de anidación:

var H 

if(C == 0){ 
    H = null; 
} 
else if(V == r){ 
    H = (g - b)/C; 
} 
else if (V == g){ 
    H = (b - r)/C + 2; 
} 
else { 
    H = (r - g)/C + 4; 
} 
+0

¿Por qué no utilizar una buena [declaración de cambio de verdad] (https: // stackoverflow.com/questions/5464362/javascript-using-a-condition-in-switch-case/9055603 # 9055603) mientras lo hace;) –

+0

@GustvandeWal te das cuenta de que esto fue respondido hace 5 años, ¿verdad? – Joseph

+0

Ooh sí, lo hago –

5

La misma lógica se puede escribir de una manera más sencilla:

var H 

if (C == 0) 
    H = null; 
else if (V == r) 
    H = (g - b)/C; 
else if (V == g) 
    H = (b - r)/C + 2; 
else 
    H = (r - g)/C + 4; 

Es posible omitir las llaves porque no hay una sola declaración en cada condición. Y dado que las condiciones son mutuamente excluyentes, usar else if es mucho más claro que anidar if s.

+1

Muy bien, gracias. En su mayoría, estaba buscando la validación lógica, solo fyi. :) –

+0

Se acepta ampliamente que los ahorros de espacio/"limpieza" de no usar corchetes se ven ampliamente superados por las implicaciones peligrosas para la mantenibilidad del código. http://stackoverflow.com/a/2125078/205192 – DougW

2

Sí, es correcto (aparte de las diferencias de mayúsculas). Sin embargo, puede ser más limpio escrito sin ningún paréntesis, legible como elseif:

if (C == 0) 
    h = null; 
else if (V == r) 
    h = (g - b)/C; 
else if (V == g) 
    h = (b - r)/C + 2; 
else 
    h = (r - g)/C + 4; 
+0

Como voy a convertir esto a Python, la sintaxis en realidad no importa. Gracias de todos modos! –

+2

Creo que el equivalente de python sería 'elif' ... el punto que todo el mundo parece querer es evitar la indentación innecesaria. –

+1

@GGG: Eso es correcto. Y si. Supongo que si eres un programador, tu instinto natural es hacer que todo sea legible ... ¡No puedo culpar a nadie por eso! –

15

Para mi gusto personal, un ternaria anidada cuidadosamente alineados mejor que el desastre había nadie más si-:

const H = 
    C == 0 ? null   : 
    V == r ? (g - b)/C  : 
    V == g ? (b - r)/C + 2 : 
      (r - g)/C + 4 ; 
3
H = C == 0 
    ? null 
    : V == r 
     ? (g - b)/C 
     : V == g 
      ? (b - r)/C + 2 
      : (r - g)/C + 4 

I He visto a Dan Abramov usando este patrón de ubicación de sangría. Aunque no me gusta cómo el operador condicional ? ya no sigue visualmente la condición, prefiero algo así como el ejemplo de @ lolmaus en que la sangría siempre será consistente independientemente del tamaño del condicional.

Realmente comienza a verlo como ? verdadero : falso que es visualmente intuitivo aquí. Y de esta manera, encuentro que el ternario es mucho más fácil de detectar y diferenciar del código circundante.