Convert task data into a flat structure I have an array of data in the below format
let input = [
{
    time: &quot;2020-7&quot;,
    tasks: [
      {
        key: &quot;p1&quot;,
        value: 15
      },
      {
        key: &quot;p2&quot;,
        value: 13
      },
    ]
  },
{
    time: &quot;2020-8&quot;,
    tasks: [
      {
        key: &quot;p1&quot;,
        value: 16
      },
      {
        key: &quot;p2&quot;,
        value: 19
      },
    ]
  },
{
    time: &quot;2020-9&quot;,
    tasks: [
      {
        key: &quot;p1&quot;,
        value: 12
      },
      {
        key: &quot;p2&quot;,
        value: 93
      },
    ]
  }
]

After config input array, then 'dataConvert' is formatted as follows:
dataConvert = [
  [&quot;x&quot;,&quot;2020-7&quot;, &quot;2020-8&quot;, &quot;2020-9&quot;],
  [&quot;p1&quot;, 15, 16, 12],
  [&quot;p2&quot;, 13, 19, 93]
]

I tried use reduce , I want to find another way of optimizing.
let dateConvert = [], valueConvert = [];
data2.forEach(x=&gt;{
   let date = new Date(x.time);
   if (date) {
      let getYear = date.getFullYear();
      let getMonth = date.getMonth() + 1;
      let newDate = `${getYear}-${getMonth}-1`;
      return dateConvert = [...dateConvert, newDate];
   }
})
dateConvert.unshift(&quot;x&quot;);

// get p1 p2 value
let allTasks = data2.flatMap(x =&gt; x.tasks);

 valueConvert = Object.values(allTasks.reduce((arr, item) =&gt; {
 arr[item.key] = arr[item.key] || [item.key];
 arr[item.key].push(item.value);
 return arr;
}, {}));
dataConvert = [...[dateConvert], ...valueConvert];

thank u.
From a short review;

The code does not produce exactly your output, the x part is different;
[&quot;x&quot;, &quot;2020-7-1&quot;, &quot;2020-8-1&quot;, &quot;2020-9-1&quot;], I assume the code is right
That reduce is fine, it's the best part of the code really
The date part seems complicated the check for the valid date could have been done in a filter, the rest in a map
Consistency is important, you use both the fancy technique dataConvert = [...[dateConvert], ...valueConvert]; and dateConvert.unshift(&quot;x&quot;); which could have been dateConvert = [&quot;x&quot;, ...dateConvert];, the only good reason for unshift could have been that dateConvert is a const but it isnt
I dont like x as a variable name, it says nothing to me, I would go for o (object)
Similarly when you reduce allTasks you pass arr as the cumulator, but it's not an array, it's an object so you could/should use o there
This [...[dateConvert], ...valueConvert]; is equivalent to [dateConvert, ...valueConvert];, you may want to play around more with the spread operator
get p1 p2 value is a very contemporary comment, it is true today because tasks indeed only contain p1 and p2, but the day that tasks get new or changed, that comment will be worthless, consider something like group all tasks properties
I guess a task is an item, but I would rather see allTasks.reduce((o, task) than allTasks.reduce((arr, item) 

If you take all that, I would counter propose this;


function convertData(data){

  let dateConvert = data.filter(o =&gt; new Date(o.time)).map(o =&gt; {
    const date = new Date(o.time);
    return `${date.getFullYear()}-${ date.getMonth() + 1}-1`;
  });
  dateConvert = ["x", ...dateConvert];

  let allTasks = data.flatMap(x =&gt; x.tasks);

  //Group all task properties
   const valueConvert = Object.values(allTasks.reduce((o, task) =&gt; {
     o[task.key] = o[task.key] || [task.key];
     o[task.key].push(task.value);
     return o;
   }, {}));

  return [dateConvert, ...valueConvert];
}

const data2 = [
{
    time: "2020-7",
    tasks: [
      {
        key: "p1",
        value: 15
      },
      {
        key: "p2",
        value: 13
      },
    ]
  },
{
    time: "2020-8",
    tasks: [
      {
        key: "p1",
        value: 16
      },
      {
        key: "p2",
        value: 19
      },
    ]
  },
{
    time: "2020-9",
    tasks: [
      {
        key: "p1",
        value: 12
      },
      {
        key: "p2",
        value: 93
      },
    ]
  }
];

console.log(convertData(data2));