How to simplify this ES6 Array code I'm just wondering Is there any ways I could simplify the following code without making it too difficult:

Actually I want to extract specific year data from content node based on lastNumberOfYears variable.

Example: Content array has 2019,2018,2017,2016 years data and lastNumberOfYears value is 2 then output should have only 2019, 2018 data. other scenario is if content array is like 2020, 2014, 2013 then output should have 2020, 2014 data (if lastNumberOfYears value is 2)

My solution

Step 1 : Define predefined data

const content = [{
    "document": "/content/path/document1.pdf",
    "date": "2020-02-20"
  }, {
    "document": "/content/path/file.docx",
    "date": "2019-02-20"
  }, {
    "document": "/content/abc/document2.docx",
    "date": "2018-06-20"
  }, {
    "document": "/document/order/order.pdf",
    "date": "2020-06-20"
  }, {
    "document": "/content/order/update.pdf",
    "date": "2018-03-21"
  }, {
    "document": "/content/author/author.pdf",
    "date": "2017-03-21"
  }, {
    "document": "/content/path/dummy.pdf",
    "date": "2016-02-15"
  }, {
    "document": "/content/dummy/dummy.docx",
    "date": "2015-12-15"
}];

let lastNumberOfYears = 2;
let selectedYearArray = [];


Step 2: Convert content data into year base data

const result = content.reduce((current, value) =&gt; {
  const dateYear = new Date(value.date).getFullYear();
  current[dateYear] = current[dateYear] || [];
  current[dateYear].push(value);
  return current;
}, {});

/*
output is like
{
   "2015":[{...}],"2016":[{}],..."2020":[{}, {}]
}
*/


Step 3: Put specific year data in same order for result array

Object.values(result).forEach(value =&gt; value.reverse());


Step 4: Create Year array from object key

const yearsArray = Object.keys(result).sort((first, second) =&gt; (first &gt; second ? -1 : 1));


Step 5: Create last number of year array using lastNumberOfYears variable
Step 6: Extract Step 5 data from result array define in step 3
Step 7: Remove year key and join all array value of Step 6 outcome

if (yearsArray.length !== 0 &amp;&amp; lastNumberOfYears &lt;= yearsArray.length) {
  for (let i = 0; i &lt; lastNumberOfYears; i++) {
    selectedYearArray.push(yearsArray[i]);
  }

  /*
    Step 5: console.log(selectedYearArray);
  */

  const filteredResult = Object.keys(result)
    .filter(key =&gt; selectedYearArray.includes(key))
    .reduce((obj, key) =&gt; {
      obj[key] = result[key];
      return obj;
    }, {});

  /*
    Step 6: console.log(filteredResult);
  */

  contentObj = [].concat.apply([],Object.values(filteredResult));

  /*
    Step 7:
  */
  console.log(contentObj.reverse());
}


Output:

[{
    "document": "/content/path/document1.pdf",
    "date": "2020-02-20"
}, {
    "document": "/document/order/order.pdf",
    "date": "2020-06-20"
}, {
    "document": "/content/path/file.docx",
    "date": "2019-02-20"
}]
Here's a scheme that appears to be about 7 times faster that yours when run in node.js:

function getData2(content, lastNumberOfYears) {
    // organize data by year into a Map object
    const map = new Map()
    for (let item of content) {
        const year = new Date(item.date).getFullYear();
        let yearData = map.get(year);
        if (yearData) {
            yearData.push(item);
        } else {
            map.set(year, [item]);
        }
    }

    /* map object data looks like this:
        Map {
          2020 =&gt; [
            { document: '/content/path/document1.pdf', date: '2020-02-20' },
            { document: '/document/order/order.pdf', date: '2020-06-20' }
          ],
          2019 =&gt; [ { document: '/content/path/file.docx', date: '2019-02-20' } ],
          2018 =&gt; [
            { document: '/content/abc/document2.docx', date: '2018-06-20' },
            { document: '/content/order/update.pdf', date: '2018-03-21' }
          ],
          2017 =&gt; [ { document: '/content/author/author.pdf', date: '2017-03-21' } ],
          2016 =&gt; [ { document: '/content/path/dummy.pdf', date: '2016-02-15' } ],
          2015 =&gt; [ { document: '/content/dummy/dummy.docx', date: '2015-12-15' } ]
        }
    */

    // get lastNumberOfYears by getting all the years, sorting them 
    // and getting most recent ones
    let sortedYears = Array.from(map.keys()).sort();
    if (sortedYears.length &gt; lastNumberOfYears) {
        sortedYears = sortedYears.slice(-lastNumberOfYears);
    }
    let result = [];
    for (let year of sortedYears) {
        result.push(map.get(year));
    }
    return result.flat();

}

function time(fn) {
    const start = process.hrtime.bigint();
    let result = fn();
    const end = process.hrtime.bigint();
    console.log(result);
    console.log(`Benchmark took ${end - start} nanoseconds`);
}


It uses the following steps:


Parse years and put each year's into a Map object with the year as the key and the value as an array of values for that year
Get the years from the Map object, sort them and get the desired lastNumberOfYears
Collect the results from the Map object for each of the chosen years and flatten them into a single array




If you want to run both yours and mine in node.js, here's the entire program I used to compare:

const inputData = [{
    "document": "/content/path/document1.pdf",
    "date": "2020-02-20"
  }, {
    "document": "/content/path/file.docx",
    "date": "2019-02-20"
  }, {
    "document": "/content/abc/document2.docx",
    "date": "2018-06-20"
  }, {
    "document": "/document/order/order.pdf",
    "date": "2020-06-20"
  }, {
    "document": "/content/order/update.pdf",
    "date": "2018-03-21"
  }, {
    "document": "/content/author/author.pdf",
    "date": "2017-03-21"
  }, {
    "document": "/content/path/dummy.pdf",
    "date": "2016-02-15"
  }, {
    "document": "/content/dummy/dummy.docx",
    "date": "2015-12-15"
}];

function getData1(content, lastNumberOfYears) {

    let selectedYearArray = [];

    const result = content.reduce((current, value) =&gt; {
      const dateYear = new Date(value.date).getFullYear();
      current[dateYear] = current[dateYear] || [];
      current[dateYear].push(value);
      return current;
    }, {});

    /*
    output is like
    {
       "2015":[{...}],"2016":[{}],..."2020":[{}, {}]
    }
    */

    Object.values(result).forEach(value =&gt; value.reverse());

    const yearsArray = Object.keys(result).sort((first, second) =&gt; (first &gt; second ? -1 : 1));

    if (yearsArray.length !== 0 &amp;&amp; lastNumberOfYears &lt;= yearsArray.length) {
      for (let i = 0; i &lt; lastNumberOfYears; i++) {
        selectedYearArray.push(yearsArray[i]);
      }

      /*
        Step 5: console.log(selectedYearArray);
      */

      const filteredResult = Object.keys(result)
        .filter(key =&gt; selectedYearArray.includes(key))
        .reduce((obj, key) =&gt; {
          obj[key] = result[key];
          return obj;
        }, {});

      /*
        Step 6: console.log(filteredResult);
      */

      contentObj = [].concat.apply([],Object.values(filteredResult));

      /*
        Step 7:
      */
      return contentObj.reverse();
    }
}

function getData2(content, lastNumberOfYears) {
    // organize data by year into a Map object
    const map = new Map()
    for (let item of content) {
        const year = new Date(item.date).getFullYear();
        let yearData = map.get(year);
        if (yearData) {
            yearData.push(item);
        } else {
            map.set(year, [item]);
        }
    }

    // get lastNumberOfYears by getting all the years, sorting them 
    // and getting most recent ones
    let sortedYears = Array.from(map.keys()).sort();
    if (sortedYears.length &gt; lastNumberOfYears) {
        sortedYears = sortedYears.slice(-lastNumberOfYears);
    }
    let result = [];
    for (let year of sortedYears) {
        result.push(map.get(year));
    }
    return result.flat();

}

function time(fn) {
    const start = process.hrtime.bigint();
    let result = fn();
    const end = process.hrtime.bigint();
    console.log(result);
    console.log(`Benchmark took ${end - start} nanoseconds`);
}

time(() =&gt; getData1(inputData, 2));

time(() =&gt; getData2(inputData, 2));


And, the output on my desktop computer was this:

[
  { document: '/content/path/document1.pdf', date: '2020-02-20' },
  { document: '/document/order/order.pdf', date: '2020-06-20' },
  { document: '/content/path/file.docx', date: '2019-02-20' }
]
Benchmark took 602501 nanoseconds
[
  { document: '/content/path/file.docx', date: '2019-02-20' },
  { document: '/content/path/document1.pdf', date: '2020-02-20' },
  { document: '/document/order/order.pdf', date: '2020-06-20' }
]
Benchmark took 89100 nanoseconds


Note a slightly different sort order of the results.  I didn't see in your description if a specific sort order of results was required or not.