Daniel H.
Daniel H.

Reputation: 680

Map children and flatten multidimensional array of objects

I am trying to map the multidimensional array of objects (below), so that the function would return a two dimensional array of objects

var UsersData = {
  data: [
    {
      label: 'CEO',
      type: 'person',
      className: 'p-person',
      expanded: true,
      data: {
        name: 'Walter White',
        avatar: 'logo_octopus.png',
      },
      children: [
        {
          label: 'CFO',
          type: 'person',
          className: 'p-person',
          expanded: true,
          data: {
            name: 'Saul Goodman',
            avatar: 'logo_octopus.png',
          },
          children: [
            {
              label: 'Tax',
              className: 'department-cfo',
            },
            {
              label: 'Legal',
              className: 'department-cfo',
            },
          ],
        },
        {
          label: 'COO',
          type: 'person',
          className: 'p-person',
          expanded: true,
          data: {
            name: 'Mike E.',
            avatar: 'logo_octopus.png',
          },
          children: [
            {
              label: 'Operations',
              className: 'department-coo',
            },
          ],
        },
        {
          label: 'CTO',
          type: 'person',
          className: 'p-person',
          expanded: true,
          data: {
            name: 'Jesse Pinkman',
            avatar: 'logo_octopus.png',
          },
          children: [
            {
              label: 'Development',
              className: 'department-cto',
              expanded: true,
              children: [
                {
                  label: 'Analysis',
                  className: 'department-cto',
                },
                {
                  label: 'Front End',
                  className: 'department-cto',
                },
                {
                  label: 'Back End',
                  className: 'department-cto',
                },
              ],
            },
            {
              label: 'QA',
              className: 'department-cto',
            },
            {
              label: 'R&D',
              className: 'department-cto',
            },
          ],
        },
      ],
    },
  ],
};

The code I was able to produce, only manages to create the desired output for the first two levels of the array above (even that, only by merging level 1 and 2).

The code I am using:

function UsersMapping(props) {
  var result = props.data;

  var lv1 = result.flatMap((value) =>
    value.children.flatMap((child) => ({
      supervisor: value.label,
      ...child,
    }))
  );
  var lv2 = lv1.flatMap((value) =>
    value.children.flatMap((child) => ({
      supervisor: value.label,
      ...child,
    }))
  );
  Array.prototype.push.apply(result, lv1);
  Array.prototype.push.apply(result, lv2);

  console.log(result);
  return result;
}

Optimally, I would like the function to go through all levels of the array, map each child to their parent ("supervisor") and create this output:

[
{label: "CEO", type: "person", className: "p-person", expanded: true, data: {name: "Walter White", avatar: "logo_octopus.png"}, …},
{supervisor: "CEO", label: "CFO", type: "person", className: "p-person", expanded: true, …},
{supervisor: "CEO", label: "COO", type: "person", className: "p-person", expanded: true, …},
{supervisor: "CEO", label: "CTO", type: "person", className: "p-person", expanded: true, …},
{supervisor: "CFO", label: "Tax", className: "department-cfo"},
{supervisor: "CFO", label: "Legal", className: "department-cfo"},
{supervisor: "COO", label: "Operations", className: "department-coo"},
{supervisor: "CTO", label: "QA", className: "department-cto"},
{supervisor: "CTO", label: "R&D", className: "department-cto"},
{supervisor: "CTO", label: "Development", className: "department-cto", expanded: true},
{supervisor: "Development", label: "Analysis", className: "department-cto"},
{supervisor: "Development", label: "Front End", className: "department-cto"},
{supervisor: "Development", label: "Back End", className: "department-cto"}
]

Any help would be highly appreciated

Upvotes: 1

Views: 1410

Answers (1)

Majed Badawi
Majed Badawi

Reputation: 28414

You need to use recursion to repeat the operation on the children items if exist. Possible solution:

const usersData = {
  data: [
    {
      label: 'CEO',
      type: 'person',
      className: 'p-person',
      expanded: true,
      data: { name: 'Walter White', avatar: 'logo_octopus.png' },
      children: [
        {
          label: 'CFO',
          type: 'person',
          className: 'p-person',
          expanded: true,
          data: { name: 'Saul Goodman', avatar: 'logo_octopus.png' },
          children: [
            { label: 'Tax', className: 'department-cfo' },
            { label: 'Legal', className: 'department-cfo' }
          ]
        },
        {
          label: 'COO',
          type: 'person',
          className: 'p-person',
          expanded: true,
          data: { name: 'Mike E.', avatar: 'logo_octopus.png' },
          children: [
            { label: 'Operations', className: 'department-coo' }
          ]
        },
        {
          label: 'CTO',
          type: 'person',
          className: 'p-person',
          expanded: true,
          data: { name: 'Jesse Pinkman', avatar: 'logo_octopus.png' },
          children: [
            {
              label: 'Development',
              className: 'department-cto',
              expanded: true,
              children: [
                { label: 'Analysis', className: 'department-cto' },
                { label: 'Front End', className: 'department-cto' },
                { label: 'Back End', className: 'department-cto' }
              ]
            },
            { label: 'QA', className: 'department-cto' },
            { label: 'R&D', className: 'department-cto' }
          ]
        }
      ]
    }
  ]
};

const transform = (arr = [], supervisor) =>
  arr.reduce((list, { children, ...e }) => {
    list.push(supervisor ? { supervisor, ...e } : e);
    if(children) list.push(...transform(children, e.label));
    return list;
  }, []);

console.log(transform(usersData.data));

Upvotes: 3

Related Questions