In my project I often find myself checking if a value is an array.
If the value is not an array I create a single element array from it.
If the value is undefined
or null
, I create an empty array.
The value itself is usually either an array of objects or a single object or undefined
const array = value ? (Array.isArray(value) ? value: [value]) : [];
Is there a more succinct way of doing this (perhaps with lodash
or underscore
), before I decide to factor this into a separate util function?
In my project I often find myself checking if a value is an array.
If the value is not an array I create a single element array from it.
If the value is undefined
or null
, I create an empty array.
The value itself is usually either an array of objects or a single object or undefined
const array = value ? (Array.isArray(value) ? value: [value]) : [];
Is there a more succinct way of doing this (perhaps with lodash
or underscore
), before I decide to factor this into a separate util function?
6 Answers
Reset to default 15You could do
var eventsArray = events ? [].concat(events) : [];
The .concat()
function accepts both arrays and individual arguments, so either way you end up with what you want.
since you are using const in your code I assume you are using ES2015 / ES6. ES1015's Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.
function abc(value = []) {
const array = Array.isArray(value) ? value: [value];
}
A condensed ES2020 way to ensure a variable is an array:
value = [].concat(value ?? [])
Explanation
As @VoteyDisciple explained, the concat function will concatenate single values or an arrays of values. The nullish coalescing operator (??) will use the value on the right (the second empty array) if the value on the left is null or undefined. So if value is null, it will concatenate an empty array to an empty array, which returns an empty array.
Examples
// Different inputs and outputs
values = [].concat([1,2,3] ?? []) // [1,2,3]
values = [].concat(1 ?? []) // [1]
values = [].concat(null ?? []) // []
// Wrap it in a function if you like
function array(value) {
return [].concat(value ?? [])
}
// Use it like this
values = array(values)
// Or even like this
for (let value of array(values)) {
console.log(value)
}
Here's a solution using lodash's castArray and isNil all wrapped up in a mixin:
_.mixin( {'asArray' : function(value){
return _.isNil(value) ? [] : _.castArray(value);
}});
Usage:
_.asArray(null) -> []
_.asArray(undefined) -> []
_.asArray(0) -> [0]
_.asArray(false) -> [false]
_.asArray([1,2,3]) -> [1,2,3]
_.asArray('wibble') -> ['wibble']
If you use ES6, you can do the following, it's cleaner than .concat()
;
function method(value = []) {
const array = [...value];
}
Even shorter solution using .flat()
There is an even slicker way to do it if you don't have to check for the undefined
or null
value. This basically converts the value to a singleton array if it was not an array before.
[value].flat()
Example usage
[12].flat() // Output: [12]
[[[12]]].flat() // Output: [[12]]
Removing nullish values
If you want to remove nullish values - just add a filter on top of that. This will remove all the values that are falsy.
[value].filter(x => x).flat()
Pitfalls
Due to the fact that 0
(and false
) is a falsy value, if you are storing numbers in an array it is advised to explicitly compare array values with null
or undefined
.
[value].filter(x => x !== null && x !== undefined).flat()
In order to shorten it a bit we could use Lodash's isNil method.
[value].filter(_.isNil).flat()