Конвертирование объекта к нужному формату

const _ = require('lodash');
const _ = require('lodash/core');

const data = {
  one: {
    section: [
      {
        name: 'This name one',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      },
      {
        name: 'This name two',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      }
    ]
  },
  two: {
    section: [
      {
        name: 'This name one two',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      },
      {
        name: 'This name two two',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      }
    ]
  },
};

getRowsForTable(data) {
   const result = _.mapValues(data, (value, key) => {
     if (!value?.sections) {
       return;
     }

     const additionalRows = value.sections.map((val: any) => {
       val.isTotal = true;
       return [...val.miningAreas, ...val.childTotals];
     });

     return {  rows: [...value.sections, ..._.flatMap(additionalRows)] };
   });

   return result;
 }
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Использую библиотеку lodash, data надо превратить на выходе к виду :

{
  one: {
    rows: [
      {
        name: 'This name one',
        paramsOne: 1,
        paramsTwo: 1,
        total: true
      },
      {
        name: 'Supp name one',
      },
      {
        name: 'Supp name two',
      },
      {
        name: 'This name two',
        paramsOne: 1,
        paramsTwo: 1,
        total: true
      },
      {
        name: 'Supp name one',
      },
      {
        name: 'Supp name two',
      }
    ]
  },
  two: {
    rows: [
      //Также как и в one
    ]
  }
}

То есть мне надо section заменить на row, в row развернуть основной объект с флагом total: true, а также добавить объекты из childArrayOne( всегда должны идти сначала), childArrayTwo.


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

Автор решения: Daniil Loban

Думаю lodash тут не сильно нужен, если объект будет обладать примерно такими же характеристиками как сейчас, можно просто понять как работают методы массивов и объектов. Основная идея сохранить все что не массив сверху, все что массив развернуть ниже, поэтому используется метод instanceof.

result = Object.entries(data).reduce((acc, [key, value]) => ({
  ...acc,
  [key]:{ rows:  // переименование section в rows
    Object.entries(value.section).reduce((acc1, [k, v]) => [
        ...acc1,

        // тут сохраняется заголовочная часть (name, total etc.)
        Object.entries(v).filter(([k1,v1]) => !(v1 instanceof Array))
          .reduce(((acc2,[k2, v2]) => ({...acc2, [k2]: v2}))
          ,{total: true}), // добавляем total 
        
        // тут разворачивается оставшаяся часть (childArrays)
        ...Object.entries(v).filter(([k1,v1]) => (v1 instanceof Array))
          .reduce((acc3, [k2, v2]) => [...acc3, ...v2], [])  
      ]
    , []) 
  }
}), {})

У меня вышло немного больше дочерних узлов... не по 2 а по 4 по причине childArrayOne(2) + childArrayTwo(2) = 4, т.е. Возможно, я не понял логики или пример нужного результата не совсем точен.

Работу можно глянуть тут:

const data = {
  one: {
    section: [
      {
        name: 'This name one',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      },
      {
        name: 'This name two',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      }
    ]
  },
  two: {
    section: [
      {
        name: 'This name one two',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      },
      {
        name: 'This name two two',
        paramsOne: 1,
        paramsTwo: 1,
        childArrayOne: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
        childArrayTwo: [
          {
            name: 'Supp name one',
          },
          {
            name: 'Supp name two',
          }
        ],
      }
    ]
  },
};

result = Object.entries(data).reduce((acc, [key, value]) => ({
  ...acc,
  [key]:{ rows:  // переименование section в rows
    Object.entries(value.section).reduce((acc1, [k, v]) => [
        ...acc1,

        // тут сохраняется заголовочная часть (name, total etc.)
        Object.entries(v).filter(([k1,v1]) => !(v1 instanceof Array)).reduce(((acc2,[k2, v2]) => ({...acc2, [k2]: v2}) )
          ,{total: true}), // добавляем total 
        
        // тут разворачивается оставшаяся часть (childArrays)
        ...Object.entries(v).filter(([k1,v1]) => (v1 instanceof Array))
          .reduce((acc3, [k2, v2]) => [...acc3, ...v2], [])  
      ]
    , []) 
  }
}), {})

// выводим результат
console.log(JSON.stringify(result, null, 2))

→ Ссылка