How to define an array with conditional elements?
JavascriptArraysJavascript Problem Overview
How can I define conditional array elements? I want to do something like this:
const cond = true;
const myArr = ["foo", cond && "bar"];
This works as expected and results in ["foo", "bar"]
but if I set cond
to false
, I get the following result: ["foo", false]
How can I define an array with a conditional element?
Javascript Solutions
Solution 1 - Javascript
You can spread an array inside of an array, in order to keep items array clean, when the condition is false
.
Here's how you can do it:
// Will result in ['foo', 'bar']
const items = [
'foo',
... true ? ['bar'] : [],
... false ? ['falsy'] : [],
]
console.log(items)
Explanations:
As you can see the ternary operator always returns an array.
If the condition is true
, then it returns ['bar']
, otherwise an empty array []
.
After that we spread out ...
the resulted array (from the ternary operation) and the array's items are pushed to the parent array.
If there aren't any array items (when the ternary check is false
), then nothing will be pushed, which is our goal.
In other answer I explained the same idea, but for objects. You can check it too here.
Solution 2 - Javascript
I'd do this
[
true && 'one',
false && 'two',
1 === 1 && 'three',
1 + 1 === 9 && 'four'
].filter(Boolean) // ['one', 'three']
Note that this will also remove falsy values, such as empty strings.
Solution 3 - Javascript
If you really want to keep it as a one liner, you could use:
const cond = true;
const myArr = ["foo"].concat(cond ? ["bar"] : []);
Solution 4 - Javascript
You can try with a simple if :
if(cond) {
myArr.push("bar");
}
Solution 5 - Javascript
You don't have so many options other than using push
:
const cond = true;
const myArr = ["foo"];
if (cond) myArr.push("bar");
Another idea is potentially adding null's and filtering them out:
const cond = true;
const myArr = ["foo", cond ? "bar" : null];
myArr = myArr.filter((item) => item !== null);
Solution 6 - Javascript
const cond = false;
const myArr = ["foo", cond ? "bar" : null].filter(Boolean);
console.log(myArr)
Will result in ["foo"]
Solution 7 - Javascript
There's a few different ways, but the way you're doing it won't really work for Javascript.
The easiest solution would be to just have an if statement.
if (myCond) arr.push(element);
There's also filter
, but I don't think that's what you want here at all, since you seem to be going for "Add this one thing, if this one condition is true" rather than checking everything against some condition. Although, if you want to get really freaky, you can do this (would not recommend, but it's cool that you can).
var arr = ["a", cond && "bar"];
arr.filter( e => e)
Basically it will just filter out all the non true values.
Solution 8 - Javascript
Add elements conditionally
/**
* Add item to array conditionally.
* @param {boolean} condition
* @param {*} value new item or array of new items
* @param {boolean} multiple use value as array of new items (for future)
* @returns {array} array to spread
* @example [ ...arrayAddConditionally(true, 'foo'), ...arrayAddConditionally(false, 'bar'), ...arrayAddConditionally(true, [1, 2, 3]), ...arrayAddConditionally(true, [4, 5, 6], true) ] // ['foo', [1, 2, 3], 4, 5, 6]
*/
export const arrayAddConditionally = (condition, value, multiple) => (
condition
? multiple ? value : [value]
: []
);
Create array with conditional elements
/**
* Create array with conditional elements
* @typedef {[condition: boolean, value: any, multiple: boolean]} ConditionalElement
* @param {(ConditionalElement|*)[]} map non-array element will be added as it is, array element must allways be conditional
* @returns {array} new array
* @example createArrayConditionally([[true, 'foo'], [false, 'baz'], [true, [1, 2, 3]], [true, [4, 5, 6], true], {}]) // ['foo', [1,2,3], 4, 5, 6, {}]
*/
export const createArrayConditionally = (map) => (
map.reduce((newArray, item) => {
// add non-conditional as it is
if (!Array.isArray(item)) {
newArray.push(item);
} else {
const [condition, value, multiple] = item;
// if multiple use value as array of new items
if (condition) newArray.push[multiple ? 'apply' : 'call'](newArray, value);
}
return newArray;
}, [])
);
Solution 9 - Javascript
This is an alternative to Jordan Enev's answer if you don't care too much about performance and it feels like you want to learn more about Javascript :)
So, if you want to do this, but without the false/undefined/null
element
['foo', true && 'bar', null && 'baz']; // ['foo', 'bar', null]
You can do it like this:
['foo', true && 'bar', ...Object.values({ ...(null && ['baz']) })]; // ['foo', 'bar']
Finally, the positive condition will work as expected:
['foo', true && 'bar', ...Object.values({ ...(true && ['baz']) })]; // ['foo', 'bar', 'baz']
Bonus: if you want to add a thing to an array, but the thing can be falsy
and then you don't want it in there, without doing a 2nd operation, here's a way to do it:
const foo = 1; // 1
const bar = (() => 'expensive result that turns out falsy for bar' && false)(); // false
const baz = (() => 'expensive result for baz')(); // 'expensive result'
const conditionalArrayWrapperFor = i => i ? [i] : [];
// tip: you can always inline conditionalWrapper if you only execute it once
// for instance, if you're using this inside a reduce call
[foo, ...conditionalArrayWrapperFor(bar), ...conditionalArrayWrapperFor(baz)] // [1, 'expensive result for baz']
Solution 10 - Javascript
Alternative approach: Pre-Filter populate instead of post filtering:
const populate = function(...values) {
return values.filter(function(el) {
return el !== false
});
};
console.log(populate("foo", true && "bar", false && "baz"))
Returns
(2) ["foo", "bar"]
I know that does not solve the shorthand notation (since it won't work no matter what you try) but it comes close to that.
Solution 11 - Javascript
if you are using es6, I would suggest
let array = [ "bike", "car", name === "van" ? "van" : null, "bus", "truck", ].filter(Boolean);
This array will only contain value "van" if name equals "van", otherwise it will be discarded.