w3schools ternario operator operador multiple javascript conditional-operator

javascript - operator - operador ternario php



Cómo escribir una expresión de operador ternario(también conocido como if) sin repetirse (16)

EDITAR: ¡Aquí está, la propuesta de Nullary-coalescing ahora en JavaScript!

Uso ||

const result = a ? a : ''fallback value'';

es equivalente a

const result = a || ''fallback value'';

Si lanzar a Boolean devuelve false , el result se le asignará ''fallback value'' , de lo contrario, el valor de a .

Tenga en cuenta el caso límite a === 0 , que se convierte en false y el result tomará (incorrectamente) ''fallback value'' . Use trucos como este bajo su propio riesgo.

PD. Los lenguajes como Swift tienen nil-coalescing operador de nil-coalescing ( ?? ), que tiene un propósito similar. Por ejemplo, en Swift escribirías result = a ?? "fallback value" result = a ?? "fallback value" que está bastante cerca del const result = a || ''fallback value''; de JavaScript const result = a || ''fallback value''; const result = a || ''fallback value'';

Por ejemplo, algo como esto:

var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0

¿Hay una mejor manera de escribir eso? Nuevamente, no estoy buscando una respuesta a la pregunta exacta anterior, solo un ejemplo de cuándo podría haber repetido operandos en expresiones de operador ternario ...


Creo que el || El operador se puede adaptar a indexOf :

var value = ((someArray.indexOf(3) + 1) || 1) - 1;

El valor devuelto se desplaza hacia arriba por 1, haciendo 0 desde -1, que es falso y, por lo tanto, se reemplaza por el segundo 1. Luego se desplaza hacia atrás.

Sin embargo, tenga en cuenta que la legibilidad es superior a evitar la repetición.


Dado el código de ejemplo en la pregunta, no está claro cómo se determinaría que 3 se establece o no en el índice 0 de someArray . -1 devuelto por .indexOf() sería valioso en este caso, con el propósito de excluir una supuesta no coincidencia que podría ser una coincidencia.

Si 3 no está incluido en la matriz, se devolverá -1 . Podemos agregar 1 al resultado de .indexOf() para evaluar como false para que el resultado sea -1 , seguido de || Operador OR y 0 . Cuando se hace referencia al value , reste 1 para obtener el índice del elemento de la matriz o -1 .

Lo que lleva de nuevo a simplemente usar .indexOf() y verificar -1 en una condición if . O bien, definir el value como undefined para evitar una posible confusión en cuanto al resultado real de la condición evaluada relacionada con la referencia original.

var someArray = [1,2,3]; var value = someArray.indexOf(3) + 1 || 1; console.log(value -= 1); var someArray = [1,2,3]; var value = someArray.indexOf(4) + 1 || 1; // how do we know that `4` is not at index `0`? console.log(value -= 1); var someArray = [1,2,3]; var value = someArray.indexOf(4) + 1 || void 0; // we know for certain that `4` is not found in `someArray` console.log(value, value = value || 0);


El código debe ser legible, por lo que ser sucinto no debe significar ser conciso sea cual sea el costo, para eso debe volver a publicarlo en https://codegolf.stackexchange.com/ , por lo que recomendaría usar una segunda variable local llamada index para maximizar la comprensión de lectura (con un costo de tiempo de ejecución mínimo también, lo noto):

var index = someArray.indexOf( 3 ); var value = index == -1 ? 0 : index;

Pero si realmente quieres reducir esta expresión, porque eres un sádico cruel con tus compañeros de trabajo o colaboradores del proyecto, entonces aquí hay 4 enfoques que puedes usar:

1: variable temporal en una instrucción var

Puede usar la capacidad de la instrucción var para definir (y asignar) un segundo index variable temporal cuando se separa con comas:

var index = someArray.indexOf(3), value = index !== -1 ? index: 0;

2: función anónima de ejecución automática

Otra opción es una función anónima de ejecución automática:

// Traditional syntax: var value = function( x ) { return x !== -1 ? x : 0 }( someArray.indexOf(3) ); // ES6 syntax: var value = ( x => x !== -1 ? x : 0 )( someArray.indexOf(3) );

3: operador de coma

También existe el infame "operador de coma" que admite JavaScript, que también está presente en C y C ++.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

Puede usar el operador de coma cuando desee incluir varias expresiones en una ubicación que requiera una sola expresión.

Puede usarlo para introducir efectos secundarios, en este caso reasignando al value :

var value = ( value = someArray.indexOf(3), value !== -1 ? value : 0 );

Esto funciona porque el var value se interpreta primero (como es una declaración), y luego la asignación de value más interna y más a la izquierda, y luego la mano derecha del operador de coma, y ​​luego el operador ternario, todo JavaScript legal.

4: reasignar en una subexpresión

El comentarista @IllusiveBrian señaló que el uso del operador de coma (en el ejemplo anterior) no es necesario si la asignación al value se usa como una subexpresión entre paréntesis:

var value = ( ( value = someArray.indexOf(3) ) !== -1 ? value : 0 );

Tenga en cuenta que el uso de negativos en expresiones lógicas puede ser más difícil de seguir para los humanos, por lo que todos los ejemplos anteriores se pueden simplificar para la lectura cambiando idx !== -1 ? x : y idx !== -1 ? x : y a idx == -1 ? y : x idx == -1 ? y : x :

var value = ( ( value = someArray.indexOf(3) ) == -1 ? 0 : value );


En realidad no, solo usa otra variable.

Su ejemplo generaliza a algo como esto.

var x = predicate(f()) ? f() : default;

Está probando un valor calculado y luego asigna ese valor a una variable si pasa algún predicado. La forma de evitar volver a calcular el valor calculado es obvia: use una variable para almacenar el resultado.

var computed = f(); var x = predicate(computed) ? computed : default;

Entiendo lo que quieres decir: parece que debería haber alguna forma de hacer esto que se vea un poco más limpia. Pero creo que esa es la mejor manera (idiomáticamente) de hacer esto. Si repitieras mucho este patrón en tu código por alguna razón, podrías escribir una pequeña función auxiliar:

var setif = (value, predicate, default) => predicate(value) ? value : default; var x = setif(someArray.indexOf(3), x => x !== -1, 0)


Esta es una solución simple con NOT bit a bit y un valor predeterminado de -1 que luego resulta en cero.

index = ~(~array.indexOf(3) || -1);

Funciona básicamente con un NOT doble a nivel de bit, que devuelve el valor original o un valor predeterminado, que después de aplicar NOT a nivel de bit devuelve cero.

Echemos un vistazo a la tabla de la verdad:

indexOf ~indexOf boolean default value result comment --------- --------- --------- --------- --------- --------- ------------------ -1 0 falsy -1 -1 0 take default value 0 -1 truthy -1 0 1 -2 truthy -2 1 2 -3 truthy -3 2


Hay dos maneras en que puedo ver al mirar su pregunta: desea reducir la longitud de la línea o específicamente evitar la repetición de una variable en un ternario. El primero es trivial (y muchos otros usuarios han publicado ejemplos):

var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0;

puede ser (y debería ser, dadas las llamadas a funciones) acortadas así:

var value = someArray.indexOf(3); value = value !== -1 ? value : 0;

Si está buscando una solución más genérica que evite la repetición de una variable en un ternario, así:

var value = conditionalTest(foo) ? foo : bar;

donde foo solo aparece una vez. Descartando soluciones de la forma:

var cad = foo; var value = conditionalTest(foo) ? cad : bar;

como técnicamente correcto pero perdiendo el punto, entonces no tienes suerte. Hay operadores, funciones y métodos que poseen la sintaxis concisa que busca, pero tales construcciones, por definición, no son operadores ternarios .

Ejemplos:

javascript, usando || para devolver el RHS cuando el LHS está falsey :

var value = foo || bar; // equivalent to !foo ? bar : foo


Me gusta la respuesta de @ slebetman. El comentario debajo expresa preocupación acerca de que la variable esté en un "estado intermedio". Si esto es una gran preocupación para usted, le sugiero encapsularlo en una función:

function get_value(arr) { var value = arr.indexOf(3); if (value === -1) { value = 0; } return value; }

Entonces solo llama

var value = get_value( someArray );

Podrías hacer más funciones genéricas si tienes usos para ellas en otros lugares, pero no manipules de más si es un caso muy específico.

Pero para ser honesto, simplemente haría como @slebetman a menos que necesite volver a usarlo desde varios lugares.


Personalmente, creo que la mejor manera de hacer esto sigue siendo la buena declaración if :

var value = someArray.indexOf(3); if (value === -1) { value = 0; }


Probablemente estés buscando un operador de fusión. Afortunadamente, podemos aprovechar el prototipo de Array para crear uno:

Array.prototype.coalesce = function() { for (var i = 0; i < this.length; i++) { if (this[i] != false && this[i] != null) return this[i]; } } [null, false, 0, 5, ''test''].coalesce(); // returns 5

Esto podría generalizarse aún más a su caso, agregando un parámetro a la función:

Array.prototype.coalesce = function(valid) { if (typeof valid !== ''function'') { valid = function(a) { return a != false && a != null; } } for (var i = 0; i < this.length; i++) { if (valid(this[i])) return this[i]; } } [null, false, 0, 5, ''test''].coalesce(); // still returns 5 [null, false, 0, 5, ''test''].coalesce(function(a){return a !== -1}); // returns null [null, false, 0, 5, ''test''].coalesce(function(a){return a != null}); //returns false


Puede usar la reasignación:

  • inicializar variable a un valor
  • use la serialización del operador && para la reasignación, porque si la primera condición es falsa, la segunda expresión no se evaluará

Ex.

var value = someArray.indexOf(3); value == -1 && (value=0);

var someArray = [4,3,2,1]; var value = someArray.indexOf(1); value == -1 && (value=0); console.log(''Found:'',value); var value = someArray.indexOf(5); value == -1 && (value=0); console.log(''Not Found:'',value);


Un ternario es como un if-else, si no necesita la parte else, ¿por qué no solo un if si?

if ((value = someArray.indexOf(3)) < 0) value = 0;


Use una función auxiliar:

function translateValue(value, match, translated) { return value === match ? translated : value; }

Ahora su código es muy legible y no hay repetición.

var value = translateValue(someArray.indexOf(3), -1, 0);

La jerarquía de las preocupaciones de codificación es:

  1. Correcto (incluido el rendimiento real o las preocupaciones de SLA)
  2. Claro
  3. Conciso
  4. Rápido

Todas las respuestas en la página hasta ahora parecen ser correctas, pero creo que mi versión tiene la mayor claridad, que es más importante que la concisión. Si no cuenta la función auxiliar, ya que puede reutilizarse, también es la más concisa. La sugerencia algo similar de usar una función auxiliar desafortunadamente usa una lambda que, para mí, simplemente oscurece lo que está haciendo. Para mí, una función más simple con un propósito que no toma una lambda, solo valores, es mucho mejor.

PD: si te gusta la sintaxis de ES6:

const translateValue = (value, match, translated) => value === match ? translated : value; let value = translateValue(someArray.indexOf(3), -1, 0); // or const


Utilice una refactorización variable de extracto :

var index = someArray.indexOf(3); var value = index !== -1 ? index : 0

Es incluso mejor con const lugar de var . También podría hacer una extracción adicional:

const index = someArray.indexOf(3); const condition = index !== -1; const value = condition ? index : 0;

En la práctica, use nombres más significativos que index , condition y value .

const threesIndex = someArray.indexOf(3); const threeFound = threesIndex !== -1; const threesIndexOrZero = threeFound ? threesIndex : 0;


Yo personalmente prefiero dos variantes:

  1. Puro si, como sugirió @slebetman

  2. Función separada, que reemplaza el valor no válido por uno predeterminado, como en este ejemplo:

function maskNegative(v, def) { return v >= 0 ? v : def; } Array.prototype.indexOfOrDefault = function(v, def) { return maskNegative(this.indexOf(v), def); } var someArray = [1, 2]; console.log(someArray.indexOfOrDefault(2, 0)); // index is 1 console.log(someArray.indexOfOrDefault(3, 0)); // default 0 returned console.log(someArray.indexOfOrDefault(3, 123)); // default 123 returned


Para números

Puede usar la función Math.max() .

var value = Math.max( someArray.indexOf(''y''), 0 );

Mantendrá los límites del resultado desde 0 hasta el primer resultado mayor que 0 si ese es el caso. Y si el resultado de indexOf es -1 , devolverá 0 como es mayor que -1 .

Para valores booleanos y booleanos

Para JS no existe una regla general AFAIK, especialmente porque se falsy valores falsy .

Pero si algo puede ayudarlo la mayor parte del tiempo es el operador o ( || ):

// Instead of var variable = this_one === true ? this_one : or_this_one; // you can use var variable = this_one || or_this_one;

indexOf tener mucho cuidado con esto, porque en su primer ejemplo, indexOf puede devolver 0 y si evalúa 0 || -1 0 || -1 devolverá -1 porque 0 es un valor falsy .