Слияние вложенных объектов в условиях более 2 уровней - PullRequest
0 голосов
/ 07 июня 2019

У меня есть массив довольно простых объектов:

[
  { category: 'A', level: 'Aa', sublevel: 'Aaa' },
  { category: 'A', level: 'Aa', sublevel: 'Aab' },
  { category: 'A', level: 'Ab', sublevel: 'Abb' },
  { category: 'B', level: 'Ac', sublevel: 'Abc' }
]

Подуровни всегда уникальны, уровни и категории могут быть одинаковыми.
Я хочу создать следующий объект из этого массива:

[
  { 
    category: 'A',
    children: [
      {
        level: 'Aa',
        children: [
          {
            sublevel: 'Aaa'
          },
          {
            sublevel: 'Aab'
          }
        ]
      },
      {
        level: 'Ab',
        children: [
          {
            sublevel: 'Abb'
          }
        ]
      }
    ]
  },
  { 
    category: 'B',
    children: [
      {
        level: 'Ac',
        children: [
          {
            sublevel: 'Abc'
}] }] }]

Другими словами, я хочу объединить category в один, если есть два объекта с одной категорией, и поместить его уровни в массив children. Если есть также объекты с одинаковыми категориями и уровнями, объедините те же уровни в один и поместите подуровни в соответствующий массив children.

Итерация по массиву на самом деле не работала с [].map и [].reduce и различными типами циклов. Также пробовал слияние lodash с и deepmerge, но подуровни для них кажутся невидимыми.

Каковы элегантные способы построения объектов в условиях с глубиной более 2 уровней?

1 Ответ

0 голосов
/ 07 июня 2019

Вам просто нужен редуктор с вложенным фильтром / картой в исходном массиве.

const categories = base.reduce((accumulator, data) => {
  let category;

  if (!accumulator.find(d => d.category === data.category)) {
    category = {
      category: data.category,
      children: [],
    };

    base
      .filter(d => d.category === data.category)
      .map(d => {
        if (!category.children.find(c => c.level === d.level)) {
          category.children.push({ level: d.level, children: [] });
        }

        const level = category.children.find(c => c.level === d.level);

        if (!level.children.find(c => c.sublevel === d.sublevel)) {
          level.children.push({ sublevel: d.sublevel });
        }
      })


    accumulator.push(category);
  }

  return accumulator;
}, []);
...