Как получить объект с вложенной структурой из массива JS

Есть массив:

response.data = [{year:2020, month:7, day:16, hour:12, minute:0, title:"Задача"},{...},{...}];

Как можно преобразовать исходный массив response.data в объект tasks со следующей структурой:

{
 '2020': {
    '7': {
      '16': {
        '12': {
          '0': 'Заголовок'
        }   
      },
      '17': {
        '12': {
          '0': 'Заголовок 2'
        }   
      }
    }
  }
}

Ожидается примерно что-то такое:

const tasks = {};
response.data.forEach((task) => {
  tasks[task.year][task.month][task.day][task.hour][task.minute] = task.title;
});

Но, естественно, так не работает. Может быть существует какой-то оптимальный способ?

UPD. Пока реализовал следующим образом:

const tasks = {};
  response.data.forEach((task) => {
    if (task) {
      if (!tasks[task.year]) tasks[task.year] = {};
      if (!tasks[task.year][task.month]) tasks[task.year][task.month] = {};
      if (!tasks[task.year][task.month][task.day]) tasks[task.year][task.month][task.day] = {};
      if (!tasks[task.year][task.month][task.day][task.hour]) tasks[task.year][task.month][task.day][task.hour] = {};
      if (!tasks[task.year][task.month][task.day][task.hour][task.minute]) tasks[task.year][task.month][task.day][task.hour][task.minute] = [];
    
    tasks[task.year][task.month][task.day][task.hour][task.minute].push(task.title);
  }
});

Выглядит глупо, но хотя бы работает.


Ответы (1 шт):

Автор решения: vsemozhebuty

Если вам нужен универсальный способ, если вы уверены, что порядок ключей в объектах всегда один и тот же и среда исполнения соблюдает этот порядок при итерации, можно попробовать так:

const data1 = [
  {year: 2020, month: 7, day: 16, hour: 12, minute: 0, title: 'Заголовок 1'},
  {year: 2020, month: 7, day: 17, hour: 12, minute: 0, title: 'Заголовок 2'},
];

const data2 = {};

for (const entry of data1) {
  let currentObject = data2;

  const values = Object.values(entry);
  const title = values.pop();
  const lastIndex = values.length - 1;

  values.forEach((value, index) => {
    if (index < lastIndex) {
      if (!currentObject[value]) currentObject[value] = {};
      currentObject = currentObject[value];
    } else {
      currentObject[value] = title;
    }
  });
}

console.log(JSON.stringify(data2, null, '  '));

Чуть менее универсально, но безоппаснее:

const data1 = [
  {year: 2020, month: 7, day: 16, hour: 12, minute: 0, title: 'Заголовок 1'},
  {year: 2020, month: 7, day: 17, hour: 12, minute: 0, title: 'Заголовок 2'},
];

const data2 = {};

for (const entry of data1) {
  let currentObject = data2;

  const values = [entry.year, entry.month, entry.day, entry.hour, entry.minute];
  const title = entry.title;
  const lastIndex = values.length - 1;

  values.forEach((value, index) => {
    if (index < lastIndex) {
      if (!currentObject[value]) currentObject[value] = {};
      currentObject = currentObject[value];
    } else {
      currentObject[value] = title;
    }
  });
}

console.log(JSON.stringify(data2, null, '  '));

→ Ссылка