5

This is my nested Object

var arr = [{
    "children": [{
        "children": [{
            "children": [],
            "Id": 1,
            "Name": "A",
            "Image": "http://imgUrl"
        }],
        "Id": 2
        "Name": "B",
        "Image": "http://imgUrl"
    }],
    "Id":3,
    "Name": "C",
    "Image": "http://imgUrl"
}]

I wanted to convert the above to the following format

[{
    "Name": "C",
    "Id": 3,
    "Image": "http://imgUrl"
}, {
    "Name": "B",
    "Id": 2,
    "Image": "http://imgUrl"
}, {
    "Name": "A",
    "Id": 1,
    "Image": "http://imgUrl"
}]

I wrote below code to do this

    var newArr = []
    function getNestedObj(obj){

        if(obj.length){
            for ( var i=0; i<obj.length; i++){
                var newObj = {};
                newObj.Name = obj[i].Name;
                newObj.Id = obj[i].Id;
                newObj.Image = obj[i].Image;
                newArr.push(newObj);

                if(obj[i].children.length !=0 ){
                    getNestedObj(obj[i].children)
                }
                else {
                    return newArr;
                }
        }
       }
    }

I want to simplify the above function? How can I achieve this?

3
  • Right now your code is working as expected? Or it is giving some error or unexpected result? If it is working, maybe you should go to codereview.stackexchange.com to ask Commented Sep 19, 2018 at 11:35
  • @ramya-selvaraj You're missing a comma after "Id": 2. I can't edit it since an edit needs to be at least 6 characters. Commented Sep 19, 2018 at 11:37
  • @JasperZelf Thanks, i'll edit now : ) Commented Sep 19, 2018 at 12:12

3 Answers 3

9

Try following

let arr = [{"children":[{"children":[{"children":[],"Id":1,"Name":"A","Image":"http://imgUrl"}],"Id":2,"Name":"B","Image":"http://imgUrl"}],"Id":3,"Name":"C","Image":"http://imgUrl"}];

function fillWithChildren(a, r=[]) {
  a.forEach(({children, ...rest}) => {
    r.push(rest);
    if(children) fillWithChildren(children, r);
  });
  return r;
}
let result = fillWithChildren(arr);
console.log(result);

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

4 Comments

Superv, +1 for using ...rest destruction from object. You could use (a, r=[]) as optional parameter in order to avoid declaration of result and manually send it, and populating in the output in the given array (supplied from calling end). Instead you can declare optional with init, and return it.
@KoushikChatterjee - Thank you for sharing your thoughts. I have incorporated it. Thanks!
@NikhilAggarwal Thanks a lot for the solution. Can you please explain it? I'm not clear about ...rest??
@RamyaSelvaraj - It is an ES6 concept, and as the name suggest it means a collection of the remaining items. For details - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… and developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
4

Recursive Reduce:

const fillWithChildren = (a = []) =>
a.reduce(
    (result, { children, ...rest }) =>
        result
            .concat(rest)
            .concat(fillWithChildren(children)),
    [],
);
fillWithChildren(arr);

1 Comment

Edited my answer: set a default value, no ternary needed anymore.
4

This can be as simple as a recursive reduce.

arr.reduce (function spr (res, cur) {
    let obj = {...cur}
    let children = obj.children
    delete obj.children;
    return children.reduce (spr, res).concat ([{
        ...obj
    }])
}, [])

let result = arr.reduce (function spr (res, cur) {
    let obj = {...cur}
    let children = obj.children;
    delete obj.children;
    return children.reduce (spr, res).concat ([{
      	...obj
    }])
}, [])

console.log (result)
<script>
var arr = [{
    "children": [{
        "children": [{
            "children": [{
                "children": [],
                "Id": 1,
                "Name": "A",
                "Image": "http://imgUrl"
            }],
            "Id": 1,
            "Name": "A",
            "Image": "http://imgUrl"
        }],
        "Id": 2,
        "Name": "B",
        "Image": "http://imgUrl"
    }],
    "Id":3,
    "Name": "C",
    "Image": "http://imgUrl"
}
, {
    "children": [{
        "children": [{
            "children": [],
            "Id": 1,
            "Name": "A",
            "Image": "http://imgUrl"
        }],
        "Id": 2,
        "Name": "B",
        "Image": "http://imgUrl"
    }],
    "Id":3,
    "Name": "C",
    "Image": "http://imgUrl"
}]
</script>

2 Comments

@StephanHovius Yes, it is? spr is the function used for reduce, look at the line children.reduce (spr,...), that's a recursive call.
Yes, I missed it. If you use spread you could make it shorter using default with rest spread: arr.reduce(function spr(res, { children = [], ...rest }) { return children.reduce(spr, res).concat(rest); }, [])

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.