Home > Net >  How can I sort Array of objects by parentId JS
How can I sort Array of objects by parentId JS

Time:09-15

How can I sort this array? I am trying to group an array of objects from a parentId that each element of the array brings, there can always be an indeterminate number of levels, the result I expect is the one I have in the output.

Input:

[
  {
    "_id": "123",
    "name": "ABC",
    "parentID": ""
  },
  {
    "_id": "645",
    "name": "ABC 2",
    "parentID": "123"
  },
  {
    "_id": "65",
    "name": "ABC 3",
    "parentID": ""
  }
]

Output:

[
  {
    "_id": "123",
    "name": "ABC",
    "parentID": "",
    "children": [
      {
        "_id": "645",
        "name": "ABC 2",
        "parentID": "123"
      },
    ]
  },
  {
    "_id": "65",
    "name": "ABC 3",
    "parentID": ""
  }
]

Thanks for help

CodePudding user response:

This should work even for nested children:

const input = [{
        "_id": "123",
        "name": "ABC",
        "parentID": ""
    },
    {
        "_id": "645",
        "name": "ABC 2",
        "parentID": "123"
    },
    {
        "_id": "65",
        "name": "ABC 3",
        "parentID": "645"
    }
]

function map(data) {
    const childMap = data.reduce((map, child) => {
        return {
            ...map,
            [child._id]: {
                ...child
            }
        };
    }, {});

    const root = [];

    Object.values(childMap).forEach((child) => {
        if (child.parentID) {
            if (childMap[child.parentID]) {
                const parent = childMap[child.parentID];
                if (!parent.children) {
                    parent.children = [];
                }

                parent.children.push(child)
            }
        } else {
            root.push(child);
        }
    })

    return root;
}

console.log(map(input));

CodePudding user response:

You can try this approach with reduce and filter

const input = [{
    "_id": "123",
    "name": "ABC",
    "parentID": ""
  },
  {
    "_id": "645",
    "name": "ABC 2",
    "parentID": "123"
  },
  {
    "_id": "65",
    "name": "ABC 3",
    "parentID": ""
  }
]

function mapChildren(data) {
  //set the output with all results having no parent ids by default
  let output = data.filter(x => !x.parentId)

  //add children to existing results
  output = data.reduce((result, current) => {
    const {
      parentID
    } = current

    if (!parentID) {
      return result
    }

    const existingRecord = result.find(x => x._id === parentID)

    if (existingRecord) {
      if(!existingRecord.children) {
        existingRecord.children = []
      }
    
      existingRecord.children.push({...current})
    }

    return result

  }, output)

  return output
}

console.log(mapChildren(input))

CodePudding user response:

Stuff like that is a job for database engines. You are not supposed to do this on Controller's side. The Model is supposed to send you data the way you want. Just ask the backend guy to make a route with the data sent like that, or just add some if statements to your data parsing method to do stuff differently based on whether an object has parentId or not.

But if you really want to do it on frontend side, you can do it like this:

const data = [
    {
        _id: '123',
        name: 'ABC',
        parentID: '',
    },
    {
        _id: '645',
        name: 'ABC 2',
        parentID: '123',
    },
    {
        _id: '65',
        name: 'ABC 3',
        parentID: '',
    },
];

const restructureData = (data) => {
    const children = data.filter((object) => object.parentID);
    const parents = data.filter((object) => !object.parentID);

    for (let i = 0; i < children.length; i  ) {
        let parentIndex = parents
            .map((object) => object._id)
            .indexOf(children[i].parentID);
        if (!parents[parentIndex].children) {
            parents[parentIndex].children = [];
        }
        parents[parentIndex].children.push(children[i]);
    }
    return parents;
};

console.log(restructureData(data));

This will not work for nested children though.

  • Related