4

In my application, I have data returned from the server like below. It has very deep nesting:

var data = [{
    name: "root",
    children: [{
            name: "Parent1",
            children: [{
                    name: "Parent1-child1",
                    children: [{
                            name: "Parent1-child1-grandchild1",
                            children: [{
                                name: "Parent1-child1-grandchild1-last",
                                children:[]
                            }]
                        },
                        {
                            name: "Parent1-child1-grandchild2",
                            children: []
                        },
                        {
                            name: "Parent1-child1-grandchild3",
                            children: []
                        }
                    ]
                },
                {
                    name: "Paren1-child2",
                    children: [{
                            name: "Parent1-chil2-grandchild1",
                            children: []
                        },
                        {
                            name: "Parent1-child2-grandchild2",
                            children: [{
                                name: "Parent1-child2-grandchild2-last",
                                children: []
                            }]
                        },
                        {
                            name: "Parent1-child2-grandchild3",
                            children: []
                        }
                    ]
                },
                {
                    name: "Parent1-child3",
                    children: []
                }
            ]
        },
        {
            name: "Parent2",
            children: [{
                    name: "Parent2-child1",
                    children: []
                },
                {
                    name: "Parent2-child2",
                    children: [{
                            name: "Parent2-child2-grandchild1",
                            children: []
                        },
                        {
                            name: "Parent2-child2-grandchild2",
                            children: [{
                                name: "Parent2-child2-grandchild2-last",
                                children: []
                            }]
                        }
                    ]
                }
            ]
        },
        {
            name: "Parent3",
            children: []
        }
    ]
}];

The requirement is to loop through all the objects (deep nested level also) and remove the object if the children property has a value of an empty array. So the output should be like below

var data = [{
    name: "root",
    children: [{
            name: "Parent1",
            children: [{
                    name: "Parent1-child1",
                    children: [{
                            name: "Parent1-child1-grandchild1",
                            children: []
                        },
                    ]
                },
                {
                    name: "Paren1-child2",
                    children: [
                        {
                            name: "Parent1-child2-grandchild2",
                            children: []
                        },
                    ]
                },
            ]
        },
        {
            name: "Parent2",
            children: [
                {
                    name: "Parent2-child2",
                    children: [
                        {
                            name: "Parent2-child2-grandchild2",
                            children: []
                        }
                    ]
                }
            ]
        }
    ]
}];

I have tried the following code, but it doesn't work as expected. Please let me know how to achieve the expected result.

function checkChildrens(arr) {
    arr.forEach((ele,i) => {
    if(ele.hasOwnProperty('children')) {
        checkChildrens(ele['children']) 
    } else {
        arr.splice(i,1)
    }
    })
}
checkChildrens(data);

I have tried with the filter method also in that case. It is not working correctly.

arr.filter((ele,i)=>{
   if(ele.hasOwnProperty('children') && ele.children.length !== 0 ){
      removeEmpty(ele.children)
   }else{
        return false;
    }
    return true;
})
3
  • Can you show the output that of this code? Commented Nov 18, 2019 at 15:26
  • 1
    The array filter method might work better for you in this situation. Commented Nov 18, 2019 at 15:27
  • You were too close to solution if(ele.hasOwnProperty('children') && ele.children.length !== 0) by checking length Commented Nov 18, 2019 at 15:47

2 Answers 2

5

You could rebuild new objects by checking the children array length.

function filter(array) {
    return array.reduce((r, o) => {
        if (o.children && o.children.length) {
            r.push(Object.assign({}, o, { children: filter(o.children) }));
        }
        return r;
    }, []);
}

var data = [{ name: "root", children: [{ name: "Parent1", children: [{ name: "Parent1-child1", children: [{ name: "Parent1-child1-grandchild1", children: [{ name: "Parent1-child1-grandchild1-last", children: [] }] }, { name: "Parent1-child1-grandchild2", children: [] }, { name: "Parent1-child1-grandchild3", children: [] }] }, { name: "Paren1-child2", children: [{ name: "Parent1-chil2-grandchild1", children: [] }, { name: "Parent1-child2-grandchild2", children: [{ name: "Parent1-child2-grandchild2-last", children: [] }] }, { name: "Parent1-child2-grandchild3", children: [] }] }, { name: "Parent1-child3", children: [] }] }, { name: "Parent2", children: [{ name: "Parent2-child1", children: [] }, { name: "Parent2-child2", children: [{ name: "Parent2-child2-grandchild1", children: [] }, { name: "Parent2-child2-grandchild2", children: [{ name: "Parent2-child2-grandchild2-last", children: [] }] }] }] }, { name: "Parent3", children: [] }] }],
    result = filter(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Approach for removing all nested empty children (except the last one. This has an empty object, but no children property).

function filter(array) {
    return array.reduce((r, o) => {
        if (o.children) {
            var children = filter(o.children);
            if (children.length) r.push(Object.assign({}, o, { children }));
        } else {
            r.push(o);
        }
        return r;
    }, []);
}

var data = [{ name: "root", children: [{ name: "Parent1", children: [{ name: "Parent1-child1", children: [{ name: "Parent1-child1-grandchild1", children: [{ name: "Parent1-child1-grandchild1-last", children: [] }] }, { name: "Parent1-child1-grandchild2", children: [] }, { name: "Parent1-child1-grandchild3", children: [] }] }, { name: "Paren1-child2", children: [{ name: "Parent1-chil2-grandchild1", children: [] }, { name: "Parent1-child2-grandchild2", children: [{ name: "Parent1-child2-grandchild2-last", children: [] }] }, { name: "Parent1-child2-grandchild3", children: [] }] }, { name: "Parent1-child3", children: [] }] }, { name: "Parent2", children: [{ name: "Parent2-child1", children: [] }, { name: "Parent2-child2", children: [{ name: "Parent2-child2-grandchild1", children: [] }, { name: "Parent2-child2-grandchild2", children: [{ name: "Parent2-child2-grandchild2-last", children: [] }] }] }] }, { name: "Parent3", children: [{}] }] }],
    result = filter(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

9 Comments

I think where this goes wrong when you remove items you also create empty children also the code should run again until no empty children has left.
@Eldar, sorry op wants empty arrays, as stated above.
Yeah noticing that took me long :)
@NinaScholz but this solution is hard to understand for newbies. you introduced reduce, assign for new developer which doesn't correctly understand recursion
@NinaScholz, thank you soooo much. As Eldar told ,if the code should run until no empty children has left means ,how to rewrite the above code
|
1

var data = [{
  name: "root",
  children: [{
      name: "Parent1",
      children: [{
          name: "Parent1-child1",
          children: [{
              name: "Parent1-child1-grandchild1",
              children: [{
                name: "Parent1-child1-grandchild1-last",
                children: []
              }]
            },
            {
              name: "Parent1-child1-grandchild2",
              children: []
            },
            {
              name: "Parent1-child1-grandchild3",
              children: []
            }
          ]
        },
        {
          name: "Paren1-child2",
          children: [{
              name: "Parent1-chil2-grandchild1",
              children: []
            },
            {
              name: "Parent1-child2-grandchild2",
              children: [{
                name: "Parent1-child2-grandchild2-last",
                children: []
              }]
            },
            {
              name: "Parent1-child2-grandchild3",
              children: []
            }
          ]
        },
        {
          name: "Parent1-child3",
          children: []
        }
      ]
    },
    {
      name: "Parent2",
      children: [{
          name: "Parent2-child1",
          children: []
        },
        {
          name: "Parent2-child2",
          children: [{
              name: "Parent2-child2-grandchild1",
              children: []
            },
            {
              name: "Parent2-child2-grandchild2",
              children: [{
                name: "Parent2-child2-grandchild2-last",
                children: []
              }]
            }
          ]
        }
      ]
    },
    {
      name: "Parent3",
      children: []
    }
  ]
}];

function checkChildrens(arr) {
  let res = []

  arr.forEach(v => {
    if (v.children && v.children.length) {
      res = res.concat({
        name: v.name,
        children: checkChildrens(v.children)
      })
    }
  })

  return res
}
console.log(checkChildrens(data));

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.