How to define an array with conditional elements?

JavascriptArrays

Javascript 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManu SchillerView Question on Stackoverflow
Solution 1 - JavascriptJordan EnevView Answer on Stackoverflow
Solution 2 - JavascriptMichael Bergquist SuarezView Answer on Stackoverflow
Solution 3 - JavascriptJames ThorpeView Answer on Stackoverflow
Solution 4 - JavascriptSylvain AttoumaniView Answer on Stackoverflow
Solution 5 - JavascriptAlberto Trindade TavaresView Answer on Stackoverflow
Solution 6 - JavascriptWestmanView Answer on Stackoverflow
Solution 7 - JavascriptAdam LeBlancView Answer on Stackoverflow
Solution 8 - JavascriptGeorgiy BukharovView Answer on Stackoverflow
Solution 9 - JavascripttibyView Answer on Stackoverflow
Solution 10 - JavascriptJankapunktView Answer on Stackoverflow
Solution 11 - JavascriptNaxxa ConsultingView Answer on Stackoverflow