Как определить массив с условными элементами?

101

как я могу определить элементы условного массива? я хочу сделать что-то вроде этого:

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

это работает как ожидалось: ["foo", "bar"]

Но если установить condна false, я получаю следующий результат:["foo", false]

Как я мог определить массив с условным элементом?

Ману Шиллер
источник
medium.com/@payelroyburman14/… ?
Роман Покровский

Ответы:

233

Вы можете распределить массив внутри массива, чтобы сохранить массив элементов в чистоте, когда условие есть false.

Вот как это сделать :

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

console.log(items)

Пояснения :

Как видите, тернарный оператор всегда возвращает массив.

Если условие - trueвозвращается ['bar'], в противном случае - пустой массив [].

После этого мы распределяем ...полученный массив (из тернарной операции), и элементы массива помещаются в родительский массив.

Если элементов массива нет (когда есть тройная проверка false), то ничего не будет отправлено , что и является нашей целью.


В другом ответе я объяснил ту же идею, но для объектов. Вы тоже можете проверить это здесь .

Джордан Энев
источник
1
Недавно мне понадобилось это сделать, и использование спреда показалось мне наиболее очевидным решением. Рад, что другие тоже используют этот шаблон. Я не хотел делать его слишком загадочным, но я собираюсь использовать его, поскольку он кажется достаточно популярным.
Brennan Cheung
Большое спасибо ~ !! я просто даже не рассматривал спред как вариант
carinlynchin
Это очень круто, не думал, что есть способ сделать это без фильтрации массива постфактум
JDune
1
Блин, вот почему я люблю Ecmascript
anni
1
Отличное решение!
catch22,
22

Я бы сделал это

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

Обратите внимание, что это также удалит ложные значения, такие как пустые строки.

Майкл Бергквист Суарес
источник
1
Мне нравится идея. Но ваша реализация будет неправильной для [true && '']. Пустая строка будет отфильтрована. Я бы предпочел использовать вспомогательную функцию вроде [foo] .filter (isNonBoolean) или [foo] .stripBoolean ()
Мартин
@Martin Да, может быть, об этом можно подробнее рассказать в ответе. Я пойду и отредактирую!
Майкл Бергквист Суарес
Думаю, возникнут проблемы, если мне понадобится такой массив: const arr = ['one', 'two', false, true]; Но идея хороша для истинной ценности :)
Санджиб Дебнат,
9

Вы можете попробовать простое, если:

if(cond) {
    myArr.push("bar");
}
Сильвен Аттумани
источник
8

Если вы действительно хотите сохранить его как один лайнер, вы можете использовать:

const cond = true;
const myArr = ["foo"].concat(cond ? ["bar"] : []);
Джеймс Торп
источник
умно, мне пригодилось для условного фронта массива т.е.const myArr = (cond ? ['item 1'] : []).concat(['item 2', 'item 3']);
devonj
6

У вас не так много вариантов, кроме использования push:

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

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

Другая идея - потенциально добавить нули и отфильтровать их:

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

myArr = myArr.filter((item) => item !== null);
Альберто Триндаде Таварес
источник
3
const cond = false;
const myArr = ["foo", cond ? "bar" : null].filter(Boolean);

console.log(myArr)

Результатом будет ["foo"]

Вестман
источник
2

Есть несколько разных способов, но то, как вы это делаете, не работает для Javascript.

Самым простым решением было бы иметь оператор if.

if (myCond) arr.push(element);

Также есть filter, но я не думаю, что это то, что вы здесь вообще хотите, поскольку вы, кажется, собираетесь «добавить это одно, если это одно условие истинно», а не проверять все на соответствие какому-то условию. Хотя, если вы хотите стать действительно причудливым, вы можете это сделать (не рекомендую, но здорово, что вы можете).

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

По сути, он просто отфильтрует все неверные значения.

Адам Леблан
источник
1
это кажется крутым. вы также можете сделать var arr = ["a", cond && "bar"].filter(e => e);@Adam LeBlanc, но вы правы, это, вероятно, мусор. но крутая фигня;)
Ману Шиллер
Это круто, но я бы не советовал использовать одно условное значение. Он лучше подходит для общего назначения типа «Избавиться от всех ложных значений». Поскольку вы просто собираетесь пройти весь массив только для одного значения. Но если у вас неопределенное количество условных значений, то это, вероятно, хорошее решение.
Adam LeBlanc
.filter (e => e) отфильтрует пустую строку.
Мартин
0

Альтернативный подход: заполнение Pre-Filter вместо пост-фильтрации:

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

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

Возврат

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

Я знаю, что это не решает проблему сокращенной записи (поскольку она не сработает, что бы вы ни пытались), но это близко к этому.

Jankapunkt
источник
0

если вы используете es6, я бы посоветовал

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

Этот массив будет содержать значение «van», только если имя равно «van», в противном случае оно будет отброшено.

Naxxa Consulting
источник
-1

если вы используете Array.push

Вы можете следовать

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

Результат ["1"]

или

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

Результат ["1","2"]

ядерный
источник
Если вы собираетесь использовать a checkи a, pushваше решение определенно не будет самым ясным. Я бы придерживался if (check) foo.push( item );вместо того, чтобы распространять пустой массив в случае ложности.
Мартин