'Simple way to force javascript to always return an array

I stumbled upon the YQL API to query for WOEIDs for use in Twitter, but I can see the output is not always in array. The API returns an object and I'm interested in value of response.query.results which returns the following:

  • if there are no results, it returns null
  • if there is only one result, it returns an object
  • if the are multiple results, it returns an array

I want the result to always be an array. I can solve this by checking the result using the following code:

var count = response.query.count;

if(count === 0) {
    return [];
} else if(count === 1) {
    var arr = [];
    arr.push(response.query.results);
    return arr;
} else {
    return response.query.results;
}

Is there a javascript or lodash function that can simplify the above code? It seems _.forEach and _.toArray will treat each property as an object if provided with a single object.



Solution 1:[1]

https://lodash.com/docs/4.17.4#concat

_.concat([],response.query.results);

would also do it.

but as @Brian pointed out, we need to handle null being equivalent to [] so you can add

_.concat([],_.isNull(response.query.results)?[]:response.query.results);

note that this is more correct because it will work for results with falsey values (like 0 and false etc)

in general, lodash is more robust than built in javascript. this usually works in your favour. one place this can trip you up is if results was a string (which is an array of characters)

https://github.com/lodash/lodash/blob/4.17.4/lodash.js#L6928

function concat() {
  var length = arguments.length;
  if (!length) {
    return [];
  }
  var args = Array(length - 1),
      array = arguments[0],
      index = length;

  while (index--) {
    args[index - 1] = arguments[index];
  }
  return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
}

Solution 2:[2]

Similar to Tom's answer above, the lodash function castArray (https://lodash.com/docs/4.17.15#castArray), introduced in Lodash v4.4, could also work for this. It has the marginal benefit that its intent is slightly more clear that [].concat(x)

const _ = require('lodash')

_.castArray(null) // [null]
_.castArray({a:1}) // [{a:1}]
_.castArray([{a:1},{a:2}] // [{a:1},{a:2}]

To deal with the null, considerations are similar to answers above, depending on how you want to handle unexpected values. A ternary with _.isNull would work, or else ?? is useful, e.g.:

const castArrayRemovingNullUndef = x => _.castArray(x ?? [])
const castArrayRemovingNull = x => _.castArray(_.isNull(x) ? [] :x)

_.castArrayRemovingNull(null) // []
_.castArrayRemovingNull({a:1}) // [{a:1}]
_.castArrayRemovingNull([{a:1},{a:2}] // [{a:1},{a:2}]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2