0

I want to create a tree from the data provided using recursion. I am also trying to get the tree to pass an npm test, but when I run the test, it is failing. I am getting a tree, but it looks different than the one it is supposed to look like.

Here is the code (with instructions in a comment):

let data = [
    { id: 'animals', parent: null },
    { id: 'mammals', parent: 'animals' },
    { id: 'cats', parent: 'mammals' },
    { id: 'dogs', parent: 'mammals' },
    { id: 'labrador', parent: 'dogs' },
    { id: 'retreiver', parent: 'dogs' },
    { id: 'corgi', parent: 'dogs' },
    { id: 'persian', parent: 'cats' },
    { id: 'siamese', parent: 'cats' },
    { id: 'maineCoon', parent: 'cats' }
];

//  write a function: makeTree(obj) 
//  that takes a flat data stucture, 
//  as seen above, and return 
//  a tree structure as seen below. 
//  Must use recursion.

function makeTree(arr, parent) {
     return arr  
     .filter((data) => data.parent === parent)
     .reduce(
         (tree, data) => [
             ...tree, 
             {
                 ...data,
                 child: makeTree(arr, data.id),
             },
         ],
         [], 
     )
}

console.log('making tree')
console.log(
    JSON.stringify(
        makeTree(data, null)
        , null, 2
    )
)

//  the tree should look like this when done
let reutrn = {
    animals: {
        mammals: {
            dogs: {
                labrador: {},
                retreiver: {},
                corgi: {},
            },
            cats: {
                persian: {},
                siamese: {},
                maineCoon: {}
            }
        }
    }
}

2
  • Recursion doesn't make much sense here. It'd be a whole lot more straightforward if it was permitted to use a different method. Commented Oct 2, 2022 at 4:00
  • Yeah, but thats the instructions i have to follow Commented Oct 2, 2022 at 4:36

2 Answers 2

3

Your reduce should produce a plain object, not an array -- there is no array in your desired output. Also, your code produces a property child, but there is no such property in your desired output. It seems like code that is specifically intended for a different output structure.

Here is the adapted reduce call:

function makeTree(arr, parent) {
    return arr  
    .filter((data) => data.parent === parent)
    .reduce(
        (tree, {id}) => ({
            ...tree, 
            [id]: makeTree(arr, id),
        }),
        {},
    );
}

const data = [{ id: 'animals', parent: null },{ id: 'mammals', parent: 'animals' },{ id: 'cats', parent: 'mammals' },{ id: 'dogs', parent: 'mammals' },{ id: 'labrador', parent: 'dogs' },{ id: 'retreiver', parent: 'dogs' },{ id: 'corgi', parent: 'dogs' },{ id: 'persian', parent: 'cats' },{ id: 'siamese', parent: 'cats' },{ id: 'maineCoon', parent: 'cats' }];
console.log(makeTree(data, null));

It should be noted that this is not an efficient way of doing it. It needs several passes of the whole array, giving this a quadratic time complexity, while an iterative method can do this with a linear time complexity.

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

Comments

2

Trincot gave you a way to fix the code you've been given.

But there is a simpler way to do this recursively, using the relatively new, but widely supported Object .fromEntries. With this, we get quite simple code:

const makeTree = (xs, root = null) => Object .fromEntries (
  xs .filter (({parent}) => parent == root) 
     .map (({id}) => [id, makeTree (xs, id)])
)

const data = [{id: 'animals', parent: null}, {id: 'mammals', parent: 'animals'}, {id: 'cats', parent: 'mammals'}, {id: 'dogs', parent: 'mammals'}, {id: 'labrador', parent: 'dogs'}, {id: 'retreiver', parent: 'dogs'}, {id: 'corgi', parent: 'dogs'}, {id: 'persian', parent: 'cats'}, {id: 'siamese', parent: 'cats'}, {id: 'maineCoon', parent: 'cats'}]

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

This has the same quadratic complexity as trincot discussed. If we wanted to we could fix that by first indexing with some sort of linear groupBy function, then doing a recursive lookup rather than a filter. I leave that as an exercise.

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.