Mike
Mike

Reputation: 13

Using JS reduce, map or filter function

Is there a more efficient way to achieve this? My desired output is to create a new array out of the following object. If supported === true, add id to array. So in below object, the output should be ['CREDIT', 'DEBIT'].

 const object = {
   "cardOptions": [
   {
      "id": "CREDIT",
      "supported": true
   },
   {
      "id": "DEBIT",
      "supported": true
   }
  ]
 }

Here is what I have now.

 const cardTypes = object.reduce((filtered, cardType) => {
      if (cardType.id && cardType.supportedAtLocation) {
          filtered.push(cardType.id)
      }
      return filtered
 }, [])

Upvotes: 0

Views: 74

Answers (1)

g2jose
g2jose

Reputation: 1465

You can also use filter + map like this:

object.cardOptions
  .filter(option => option.supported)
  .map(cardOption => cardOption.id)

Profiling this side by side using the User Timing API, at least on chrome, it seems like your reduce code is more efficient (but practically it probably won't matter unless you have a really large dataset).

Here's a quick higher order profiling function I often use:

// A function to run an input function several times and profile performance using the User Timing API on chrome
const profile = (func, times) => (...args) => {
    const functionName = func.name;
    const trackName = `${functionName}`;
    const startTag = `${trackName}_start`;
    window.performance.mark(startTag);
    let results;
    for (let i = 0; i < times; i = i + 1)
        results = func(...args);
    const endTag = `${trackName}_end`;
    window.performance.mark(endTag);
    window.performance.measure(trackName, startTag, endTag);
    return results;
};
const object = {
    cardOptions: [
        {
            id: 'CREDIT',
            supported: true,
        },
        {
            id: 'DEBIT',
            supported: true,
        },
    ],
};
const filterMap = () => {
    object.cardOptions
        .filter(option => option.supported)
        .map(cardOption => cardOption.id);
};
const reduce = () => {
    object.cardOptions.reduce((filtered, cardType) => {
        if (cardType.id && cardType.supported) {
            filtered.push(cardType.id);
        }
        return filtered;
    }, []);
};

profile(filterMap, 99999)();
profile(reduce, 99999)();

The output of the measure looks like so:

window.performance.getEntriesByType('measure')

[
  {
    name: 'profileFilterMap',
    entryType: 'measure',
    startTime: 310637.6400000008,
    duration: 30.029999994440004, // higher duration for map + filter
  },
  {
    name: 'profileReduce',
    entryType: 'measure',
    startTime: 310667.7550000022,
    duration: 24.754999991273507, // reduce seems slightly more efficient
  },
]

Upvotes: 2

Related Questions