¿Cómo definir una matriz con elementos condicionales?

101

¿Cómo puedo definir elementos de matriz condicional? quiero hacer algo como esto:

const cond = true;
const myArr = ["foo", cond && "bar"];

esto funciona como se esperaba: ["foo", "bar"]

Pero si me puse conda false, me sale el siguiente resultado:["foo", false]

¿Cómo podría definir una matriz con un elemento condicional?

Manu Schiller
fuente

Respuestas:

233

Puede extender una matriz dentro de una matriz, para mantener limpia la matriz de elementos, cuando la condición es false.

Así es como puede hacerlo :

// Will result in ['foo', 'bar']
const items = [
  'foo',
  ... true ? ['bar'] : [],
  ... false ? ['falsy'] : [],
]

console.log(items)

Explicaciones :

Como puede ver, el operador ternario siempre devuelve una matriz.

Si la condición es true, regresa ['bar']; de lo contrario, una matriz vacía [].

Después de eso, distribuimos ...la matriz resultante (de la operación ternaria) y los elementos de la matriz se envían a la matriz principal.

Si no hay elementos de la matriz (cuando la verificación ternaria es false), no se enviará nada, que es nuestro objetivo.


En otra respuesta expliqué la misma idea, pero para objetos. Puedes comprobarlo también aquí .

Jordan Enev
fuente
1
Hace poco necesitaba hacer esto y usar spread me pareció la solución más obvia. Me alegro de que otros también estén usando este patrón. No quería que fuera demasiado críptico, pero voy a seguir con él ya que parece lo suficientemente popular.
Brennan Cheung
muchas gracias ~ !! Simplemente ni siquiera consideré la propagación como una opción
carinlynchin
Esto es muy bueno, no pensé que habría una manera de hacer esto sin filtrar la matriz después del hecho
JDune
1
Maldita sea, por eso amo Ecmascript
anni
1
Excelente solucion!
catch22
22

Yo haría esto

[
  true && 'one',
  false && 'two',
  1 === 1 && 'three',
  1 + 1 === 9 && 'four'
].filter(Boolean) // ['one', 'three']

Tenga en cuenta que esto también eliminará los valores falsos , como cadenas vacías.

Michael Bergquist Suárez
fuente
1
Me gusta la idea. Pero su implementación sería incorrecta para [true && '']. La cadena vacía se filtraría. Preferiría usar una función auxiliar como [foo] .filter (isNonBoolean) o [foo] .stripBoolean ()
Martin
@Martin Sí, tal vez eso podría explicarse en la respuesta. ¡Seguiré adelante y lo editaré!
Michael Bergquist Suarez
Creo que habrá un problema si necesito una matriz como esta: const arr = ['uno', 'dos', falso, verdadero]; Pero la idea es buena por el valor de la verdad :)
Sanjib Debnath
9

Puedes probar con un simple si:

if(cond) {
    myArr.push("bar");
}
Sylvain Attoumani
fuente
8

Si realmente desea mantenerlo como una sola línea, puede usar:

const cond = true;
const myArr = ["foo"].concat(cond ? ["bar"] : []);
James Thorpe
fuente
inteligente, fue útil para mí para el frente condicional de la matriz, es decirconst myArr = (cond ? ['item 1'] : []).concat(['item 2', 'item 3']);
devonj
6

No tienes tantas opciones además de usar push:

const cond = true;
const myArr = ["foo"];

if (cond) myArr.push("bar");

Otra idea es potencialmente agregar nulos y filtrarlos:

const cond = true;
const myArr = ["foo", cond ? "bar" : null];

myArr = myArr.filter((item) => item !== null);
Alberto Trindade Tavares
fuente
3
const cond = false;
const myArr = ["foo", cond ? "bar" : null].filter(Boolean);

console.log(myArr)

Resultará en ["foo"]

Westman
fuente
2

Hay algunas formas diferentes, pero la forma en que lo está haciendo realmente no funcionará para Javascript.

La solución más sencilla sería tener una declaración if.

if (myCond) arr.push(element);

También hay filter, pero no creo que eso sea lo que quieres aquí en absoluto, ya que parece que estás optando por "Agregar esta única cosa, si esta única condición es verdadera" en lugar de comparar todo con alguna condición. Aunque, si quieres ponerte realmente raro, puedes hacerlo (no lo recomendaría, pero es genial que puedas).

var arr = ["a", cond && "bar"];
arr.filter( e => e)

Básicamente, solo filtrará todos los valores no verdaderos.

Adam LeBlanc
fuente
1
esto parece genial. también podrías hacer var arr = ["a", cond && "bar"].filter(e => e);@Adam LeBlanc pero tienes razón, probablemente sea basura. pero basura fresca;)
Manu Schiller
Es genial, pero lo desaconsejaría solo por un valor condicional. Es más adecuado para un propósito general del tipo "Deshacerse de todos los valores falsos". Ya que solo terminará revisando toda la matriz por un solo valor. Pero si tiene una cantidad indeterminada de valores condicionales, probablemente sea una buena solución.
Adam LeBlanc
.filter (e => e) filtraría la cadena vacía.
Martin
0

Enfoque alternativo: Prefiltro rellenar en lugar de posfiltrar:

const populate = function(...values) {
    return values.filter(function(el) {
        return el !== false
    });
};

console.log(populate("foo", true && "bar", false && "baz"))

Devoluciones

(2) ["foo", "bar"]

Sé que no resuelve la notación abreviada (ya que no funcionará sin importar lo que intentes) pero se acerca a eso.

Jankapunkt
fuente
0

si está usando es6, sugeriría

let array = [ "bike", "car", name === "van" ? "van" : null, "bus", "truck", ].filter(Boolean);

Esta matriz solo contendrá el valor "van" si el nombre es igual a "van", de lo contrario, se descartará.

Consultoría Naxxa
fuente
-1

si utiliza Array.push

Puedes seguir

var a = ["1"]
a.push(... !true ? ["2"] : [])

El resultado es ["1"]

o

var a = ["1"]
a.push(... true ? ["2"] : [])

El resultado es ["1","2"]

nuclear
fuente
Si va a utilizar una checky una pushsolución definitivamente no es el que tiene la mayor claridad. Me quedaría con en if (check) foo.push( item );lugar de extender una matriz vacía en el caso falso.
Martin