0
I have an array of objects like this
    const ticketsData = [
            { id: 1, title: 'parent', parent: 0, url: '' },
            { id: 2, title: 'parent', parent: 0, url: '' },
            { id: 3, title: 'child', parent: 1, url: '' },
            { id: 4, title: 'sub child', parent: 3, url: '' },
            { id: 5, title: 'sub sub child', parent: 4, url: '' },
            { id: 6, title: 'sub sub sub child', parent: 5, url: '' },
            { id: 10, title: 'sub sub child 2', parent: 4, url: '' },
            { id: 13, title: 'sub child 2', parent: 3, url: '' },
            { id: 14, title: 'child', parent: 2, url: '' },
            { id: 7, title: 'sub sub sub child', parent: 5, url: '' },
            { id: 8, title: 'sub sub sub child', parent: 5, url: '' },
            { id: 9, title: 'sub sub sub child', parent: 5, url: '' },
            { id: 11, title: 'sub sub child 3', parent: 4, url: '' },
            { id: 12, title: 'sub sub child 4', parent: 4, url: '' }
          ];

and I want to create a nested array of object upto a limit, say 10. So when the count reduces to zero it should return the array till that child/parent.

> This is my expected Output:

    [{ id: 1, title: 'parent', parent: 0, url: '', children: [
{ id: 3, title: 'child', parent: 1, url: '', children:[
{ id: 4, title: 'sub child', parent: 3, url: '', children:[
{ id: 5, title: 'sub sub child', parent: 4, url: '' , children:[
{ id: 6, title: 'sub sub sub child', parent: 5, url: '', children:[] },
{ id: 7, title: 'sub sub sub child', parent: 5, url: '', children:[] },
{ id: 8, title: 'sub sub sub child', parent: 5, url: '', children:[] },
{ id: 9, title: 'sub sub sub child', parent: 5, url: '', children:[] }
]},
{ id: 10, title: 'sub sub child 2', parent: 4, url: '', children:[] },
{ id: 11, title: 'sub sub child 3', parent: 4, url: '', children:[] }
] }
] }
] }]

I tried this but getting all the objects in separate array.

     const createTicketTree = (tickets, count) => {
        let ticketObj = {};
        let ticketHierarchy = []
        tickets.map( ticket => {
          ticketObj[ticket.id] = { ...ticket, children: [] };
            if(ticket.parent && count && count--) {
              ticketObj[ticket.parent].children.push(ticketObj[ticket.id]) 
             }
            else { 
            ticketHierarchy.push(ticketObj[ticket.id]) 
            }
        });
        return ticketHierarchy;
    };

This is how I am calling the function to get the nested parent-children relation upto 10. Is there any lodash/underscore implementation to acheive this? Any help would be appreciated

    createTicketTree(ticketsData, 10);
7
  • 2
    do you have an example of the wanted result? Commented Jul 20, 2020 at 15:55
  • share the expected output format Commented Jul 20, 2020 at 16:10
  • @NinaScholz: Updated my expected output Commented Jul 20, 2020 at 16:19
  • is the array sorted? why not take the first n objects and build a tree from it? Commented Jul 20, 2020 at 16:47
  • actually i don't get the point of havin a limit. do you want a full branch of the tree if the parent is in the count or is the limit the depth of wanted nesting parts? Commented Jul 20, 2020 at 16:58

2 Answers 2

1

You could use recursive approach with reduce method and keep count of added elements inside one variable and check if the count is less then 0 to stop adding elements to array.

const ticketsData = [{"id":1,"title":"parent","parent":0,"url":""},{"id":2,"title":"parent","parent":0,"url":""},{"id":3,"title":"child","parent":1,"url":""},{"id":4,"title":"sub child","parent":3,"url":""},{"id":5,"title":"sub sub child","parent":4,"url":""},{"id":6,"title":"sub sub sub child","parent":5,"url":""},{"id":10,"title":"sub sub child 2","parent":4,"url":""},{"id":13,"title":"sub child 2","parent":3,"url":""},{"id":14,"title":"child","parent":2,"url":""},{"id":7,"title":"sub sub sub child","parent":5,"url":""},{"id":8,"title":"sub sub sub child","parent":5,"url":""},{"id":9,"title":"sub sub sub child","parent":5,"url":""},{"id":11,"title":"sub sub child 3","parent":4,"url":""},{"id":12,"title":"sub sub child 4","parent":4,"url":""}]

let count = 10;

function createTicketTree(data, pid = 0) {
  return data.reduce((r, e) => {
    if (e.parent === pid && count > 0) {
      count--
      const o = { ...e }
      const c = createTicketTree(data, e.id);
      if (c.length) o.children = c;
      r.push(o)
    }

    return r;
  }, [])
}

const result = createTicketTree(ticketsData);
console.log(result)

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

6 Comments

Thanks @Nenad, this works perfect. Is there a way do to it without recursion due to performance issues?
I was referring to playcode.io/316025, I will accept this answer though as there is not much difference in performance. Thanks again for saving my day.
You could add some optimization like this jsfiddle.net/qm9yghpe/4 where the data pool gets smaller and smaller.
You could also go with plain for loops if the performance is important here jsfiddle.net/6ozve92d/1
can we use this count variable inside the function? As i have to pass this in my function from my state in react.
|
0

I don't think the if condition is what you're looking for. count isn't getting modified or saved anywhere. I would modify the if statement to check for the length of the parent ticket's children, compared to the count:

if(ticket.parent && ticketObj[ticket.parent].children.length < count)

However, I am confused about what the end result is you're looking for, and how you're counting the nested objects in the children list.

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.