Home > Software design >  Is there a shorter way to achieve this filter of data types?
Is there a shorter way to achieve this filter of data types?

Time:11-21

I have to come up with a function that pushes data into its own category. This is what I made & it passes the tests required. My question is if there is a much shorter way in ES6 to write this, don´t really like using switches.

function filterTypes(values) {
  const result = {
    number: [],
    string: [],
    object: [],
    others: [],
  };

  for (const value of values) {
    switch (typeof value) {
      case "number":
        result.number.push(value);
        break;
      case "string":
        result.string.push(value);
        break;
      case "object":
        // null is a falsy object so if null --> push to others
        value === null ? result.others.push(value) : result.object.push(value);
        break;
      default:
        // undefined, bigint, symbol, boolean, function
        result.others.push(value);
    }
  }

  return result;
}


CodePudding user response:

Since the keys of your object match the string value you get when you use typeof, you can use the result of calling typeof on each value to determine the key you want to push to. You can add some expectations such as if the value is null to use "other" as the key instead of "object". If the typeof the value isn't in your result object you're building, you can also choose "other" (below I've used Object.hasOwn() to check if the type is in the object which is part of ECMAScript 2022, you can use Object.prototype.hasOwnProperty() or the in operator for older browser support).

See the example below (see browser console to view big int):

function filterTypes(values) {
  const result = {number: [], string: [], object: [], others: []};
  for(const value of values) {
    const type = typeof value;
    const key = value === null || !Object.hasOwn(result, type) ? "others" : type;
    result[key].push(value);
  }

  return result;
}

console.log(filterTypes([0, "a", {x: 1}, 1n, null, true]));

A similar result can be achieved if you use .reduce(), but a regular for...of loop is easier to read in my opinion. In the below example I'm building up an accumulated object with the spread syntax (...) which is returned from the reduce callback, that also has an updated key value to hold a new array with the current value:

const filterTypes = values => values.reduce((acc, value) => {
  const type = typeof value;
  const key = value === null || !Object.hasOwn(acc, type) ? "others" : type;
  return {...acc, [key]: [...acc[key], value]};
}, {number: [], string: [], object: [], others: []});

console.log(filterTypes([0, "a", {x: 1}, 1n, null, true]));

  • Related