Search code examples
javascriptreactjsarraysobjectreduce

How to rearrange a object with multiple levels based on groups and ascending order?


I need to rearrange a chained object to a non-chained one. So, I need to create more objects to represent this.

basicaly I have this:

1. Person (code:1) (level 1)
 1.2 Person (code:2) (level 2)
  1.2.1 Person (code:3) (level 3)
 1.3 Person (code:4) (level 2)
  1.3.1 Person (code:5) (level 3)
  1.3.2 Person (code:6) (level 3)

And, expect this:

  1. Person (code:1) (level 1)
  2. Person (code:2) (level 2)
  3. Person (code:3) (level 3)
  4. Person (code:4) (level 2)
  5. Person (code:5) (level 3)
  6. Person (code:6) (level 3)

Now, in real world. My object:

[
    {
        "id": 5,
        "name": "Jhon",
        "code": "2",
        "employee_lvl2": [
            {
                "id": 23,
                "name": "Rodolf (John's employee 1)",
                "code": "9",
                "employee_lvl3": [
                    {
                        "id": 5,
                        "name": "Marcus (Rodolf's employee 1)",
                        "code": "18"
                    }
                ]
            },
            {
                "id": 17,
                "name": "Samuel (John's employee 2)",
                "code": "16",
                "employee_lvl3": [
                    {
                        "id": 11,
                        "name": "Jacob (Samuel's employee 1)",
                        "code": "21"
                    },
                    {
                        "id": 18,
                        "name": "Agnes (Samuel's employee 2)",
                        "code": "31"
                    }
                ]
            }
        ]
    },
    {
        "id": 4,
        "name": "Jennifer",
        "code": "1",
        "employee_lvl2": [
            {
                "id": 8,
                "name": "James (Jennifer's employee 1)",
                "code": "3",
                "employee_lvl3": [
                    {
                        "id": 12,
                        "name": "Jonathan (James's employee 1)",
                        "code": "8"
                    },
                    {
                        "id": 8,
                        "name": "Agnes (James's employee 2)",
                        "code": "3"
                    }
                ]
            },
            {
                "id": 7,
                "name": "Julie (Jennifer's employee 2)",
                "code": "6",
                "employee_lvl3": [
                    {
                        "id": 1,
                        "name": "Jacob (Julie's employee 1)",
                        "code": "1"
                    }
                ]
            }
        ]
    }
]

I expect something like: (ordered by code in all levels and stacking code in a property "stacked_code")

[
    {
        "id": 4,
        "name": "Jennifer",
        "code": "1"
    },
    {
        "id": 8,
        "name": "James (Jennifer's employee 1)",
        "code": "3",
        "stacked_code": "1.3"
    },
    {
        "id": 8,
        "name": "Agnes (James's employee 2)",
        "code": "3",
        "stacked_code": "1.3.3"
    },
    {
        "id": 12,
        "name": "Jonathan (James's employee 1)",
        "code": "8",
        "stacked_code": "1.3.8"
    },
    {
        "id": 7,
        "name": "Julie (Jennifer's employee 2)",
        "code": "6",
        "stacked_code": "1.6"
    },
    {
        "id": 1,
        "name": "Jacob (Julie's employee 1)",
        "code": "1",
        "stacked_code": "1.6.1"
    },
    {
        "id": 5,
        "name": "Jhon",
        "code": "2"
    },
    {
        "id": 23,
        "name": "Rodolf (John's employee 1)",
        "code": "9",
        "stacked_code": "2.9"
    },
    {
        "id": 5,
        "name": "Marcus (Rodolf's employee 1)",
        "code": "18",
        "stacked_code": "2.9.18"
    },
    {
        "id": 17,
        "name": "Samuel (John's employee 2)",
        "code": "16",
        "stacked_code": "2.16"
    },
    {
        "id": 11,
        "name": "Jacob (Samuel's employee 1)",
        "code": "21",
        "stacked_code": "2.16.21"
    },
    {
        "id": 18,
        "name": "Agnes (Samuel's employee 2)",
        "code": "31",
        "stacked_code": "2.16.31"
    }
]

I tried using some map() and push array but nothing significant. I know this somehow works with reduce but I can't help myself at the moment.


Solution

  • You can use a recursive function to solve this problem.

    const outputArr = [];
    
    /**
     * Convert a multilevel person object into one level
     * @param {Object} person The person object
     */
    const convertToOneLevel = (person, parentCode = null) => {
      const newPerson = {
        id: person.id,
        name: person.name,
        code: person.code,
        stacked_code: parentCode ? `${parentCode}.${person.code}` : undefined,
      };
      outputArr.push(newPerson);
      const idx = Object.keys(person).findIndex((key) =>
        key.startsWith('employee_lvl')
      );
      if (idx !== -1) {
        person[Object.keys(person)[idx]].map((p) =>
          convertToOneLevel(
            p,
            newPerson.stacked_code ? newPerson.stacked_code : newPerson.code
          )
        );
      }
    };
    
    obj.forEach((p) => convertToOneLevel(p));
    

    There obj is your input object.

    Outpur array will be looked like-

    [
      { id: 5, name: 'Jhon', code: '2', stacked_code: undefined },
      {
        id: 23,
        name: "Rodolf (John's employee 1)",
        code: '9',
        stacked_code: '2.9'
      },
      {
        id: 5,
        name: "Marcus (Rodolf's employee 1)",
        code: '18',
        stacked_code: '2.9.18'
      },
      {
        id: 17,
        name: "Samuel (John's employee 2)",
        code: '16',
        stacked_code: '2.16'
      },
      {
        id: 11,
        name: "Jacob (Samuel's employee 1)",
        code: '21',
        stacked_code: '2.16.21'
      },
      {
        id: 18,
        name: "Agnes (Samuel's employee 2)",
        code: '31',
        stacked_code: '2.16.31'
      },
      { id: 4, name: 'Jennifer', code: '1', stacked_code: undefined },
      {
        id: 8,
        name: "James (Jennifer's employee 1)",
        code: '3',
        stacked_code: '1.3'
      },
      {
        id: 12,
        name: "Jonathan (James's employee 1)",
        code: '8',
        stacked_code: '1.3.8'
      },
      {
        id: 8,
        name: "Agnes (James's employee 2)",
        code: '3',
        stacked_code: '1.3.3'
      },
      {
        id: 7,
        name: "Julie (Jennifer's employee 2)",
        code: '6',
        stacked_code: '1.6'
      },
      {
        id: 1,
        name: "Jacob (Julie's employee 1)",
        code: '1',
        stacked_code: '1.6.1'
      }
    ]