0

I have a nested array of objects which I need to convert to one dimensional Array of objects. In the final Array the 'childrens' is not required.

"Edit": I also need to concatenate the path values of childrens

Original Array

const data = [
{
    title: "Dashboard",
    icon: "Dashboard",
    page:"<Dashboard./>",
    path: "dashboard"                
},
{
    title: "Management",
    icon: "Management",
    page:"<Management/>",
    path: "manage",
    childrens:[
        {
            title: "Assets",
            icon: "Dot",
            page:"<Assetshome/>",
            path: "assets",
            childrens:[
        
                {
                    title: "MyAssets",
                    icon: "Dot",
                    page:"<Myassets/>",
                    path: "myassets"

                },
                {
                    title: "AddAssets",
                    icon: "Dot",
                    page:"<Addassets/>",
                    path: "addassets"

                }                    
            ]
        },
        {
            title: "Users",
            icon: "Dot",
            page: "<Users/>"
            path: "users"
        },
        {
            title: "Office",
            icon: "Dot",
            page:"<Office/>"
            path: "office"
        }            

    ]
},
{
    title: "Reports",
    icon: "Reports",
    page:"<Reports/>"
    path: "reports"
} 

]

Required flattened Array having path values of childrens concatenated.

const newdata = [
{
    title: "Dashboard",
    icon: "Dashboard",
    page:"<Dashboard/>",
    path: "dashboard"
            
},
{
    title: "Management",
    icon: "Management",
    page:"<Management/>",
    path: "manage"
},
{
    title: "Assets",
    icon: "Dot",
    page:"<Assetshome/>",
    path: "manage/assets"
},
        
{
    title: "MyAssets",
    icon: "Dot",
    page:"<Myassets/>",
    path: "manage/assets/myassets"

},
{
    title: "AddAssets",
    icon: "Dot",
    page:"<Addassets/>",
    path: "manage/assets/addassets"

},               
       
{
    title: "Users",
    icon: "Dot",
    page: "<Users/>"
    path: "users"
},
{
    title: "Office",
    icon: "Dot",
    page:"<Office/>"
    path: "office"
},   
{
    title: "Reports",
    icon: "Reports",
    page: "<Reports/>"
    path: "reports"
} 

]

What is the best way to do this in javascript.

2 Answers 2

1
const flatten = (source, basepath, list=[]) => {
    for (objs of source) {
        let {childrens, path, ...item} = objs
        item.path = basepath ? basepath + '/' + path : path
        list.push(item)
        if (childrens) {
            flatten(childrens, item.path, list)
        }
    }
    return list
}

const newdata = flatten(data)

Note that the childrens and path variables above use the object destructuring assignment, so they need to have the same names as the object keys for your child arrays and path string. (The other variable names aren't important).

I tested it on your source data and it seems to work, once I fixed the missing commas in your supplied json.

Edited to retain the path for subarrays.

Sign up to request clarification or add additional context in comments.

3 Comments

Its working. Thanks a ton. A clarification request, why have you taken "for (objs of (source || []))" and not just "for (objs of source)". One more thing i missed in the question, In the flattened data is it possible to have the path value of childrens retain the parent path eg. for Assets, the path would be "manage/assets". Similarly for Addassets, "manage/assets/addassets".
@NewCoder for (objs of (source || [])) just defaults the source variable to an empty array, because it ends up undefined at the bottom of the tree when there's no childrens sub-array. This could also be done by checking whether the value is undefined before continuing. Honestly, that was a bit of a lazy hack on my part, I'll switch it when I add the path part.
@NewCoder I added an extra optional parameter to the recursive function for the parent's path, and made it concatenate that with the current path only when basepath exists. That should do what you want.
0

Possible solution

function extractRecursive(current) {
  const { childrens, ...props } = current;
  const data = [{ ...props }];
  if (current.childrens) {
    current.childrens.forEach((innerChild) => {
      const innerChilds = extractRecursive(innerChild);
      data.push(...innerChilds);
    });
  }
  return data;
}

const flattenData = [];
data.forEach(obj => {
  flattenData.push(
    ...extractRecursive(obj)
  )
})

Stackblitz Snippet

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.