Transform list into a tree (tree node) – JavaScript

  javascript, vue.js, vuex

I have a list (an array of objects), in which they can have parents or not.

const categories = [
  { value: 1, text: 'Food', parent_id: null },
  { value: 2, text: 'Services', parent_id: null },
  { value: 3, text: 'Amazon Prime', parent_id: 2 },
  { value: 4, text: 'Netlix', parent_id: 2 },
  { value: 5, text: 'Beauty', parent_id: null },
  { value: 6, text: 'Education', parent_id: null },
  { value: 8, text: 'Academy', parent_id: 6 },
  { value: 9, text: 'Taxes', parent_id: null },
  { value: 10, text: 'Fees', parent_id: 9 },
  { value: 11, text: 'Recreation', parent_id: null },
  { value: 12, text: 'Pub', parent_id: 11 },
  { value: 13, text: 'House', parent_id: null },
  { value: 15, text: 'Illumination', parent_id: 13 },
  { value: 16, text: 'Internet', parent_id: 13 },
  { value: 18, text: 'Pets', parent_id: null },
  { value: 19, text: 'Award', parent_id: null },
  { value: 20, text: 'Gifts', parent_id: null },
  { value: 21, text: 'Salary', parent_id: null },
  { value: 22, text: 'Health', parent_id: null },
  { value: 23, text: 'Doctor', parent_id: 22 },
  { value: 24, text: 'Pharmacy', parent_id: 22 },
  { value: 25, text: 'Transport', parent_id: null },
  { value: 26, text: 'Trip', parent_id: null },
  { value: 27, text: 'NY', parent_id: 27 },
  { value: 28, text: 'Investment', parent_id: 9 },
  { value: 29, text: 'Bakery', parent_id: 1 },
  { value: 30, text: 'Restaurant', parent_id: 1 },
  { value: 31, text: 'Marketplace', parent_id: 1 },
  { value: 32, text: 'Rent', parent_id: 13 },
  { value: 33, text: 'Phone', parent_id: 13 },
  { value: 34, text: 'Reforms', parent_id: 13 },
  { value: 35, text: 'Telecine', parent_id: 2 },
  { value: 36, text: 'Appliances', parent_id: 13 },
  { value: 37, text: 'Disney', parent_id: 2 },  
  { value: 38, text: 'Water', parent_id: 13 },
  { value: 39, text: 'Kitchen', parent_id: 35 },
  { value: 40, text: 'Furniture', parent_id: 40 },
  { value: 41, text: 'Construction Materials', parent_id: 40 },
]

export default categories;

I need to transform this list into a tree, making it from a comparison: if it has the tag_parent_id, and if it is equal to the value of some other item, it is a child! The result would have to be like this:

const categories = [
  { value: 1, text: 'Food', parent_id: null, children: [
    { value: 29, text: 'Bakery', parent_id: 1 },
    { value: 30, text: 'Restaurant', parent_id: 1 },
    { value: 31, text: 'Marketplace', parent_id: 1 },
  ] },
  { value: 2, text: 'Services', parent_id: null, children: [
    { value: 3, text: 'Amazon Prime', parent_id: 2 },
    { value: 4, text: 'Netlix', parent_id: 2 },
    { value: 35, text: 'Telecine', parent_id: 2 },
    { value: 37, text: 'Dinsey', parent_id: 2 },  
  ] },
  { value: 5, text: 'Beauty', parent_id: null },
  { value: 6, text: 'Education', parent_id: null, children: [
    { value: 8, text: 'Academy', parent_id: 6 },
  ] },
  { value: 9, text: 'Taxes', parent_id: null, children: [
    { value: 28, text: 'Investment', parent_id: 9 },
    { value: 10, text: 'Fees', parent_id: 9 },
  ] },
  { value: 11, text: 'Recreation', parent_id: null, children: [
    { value: 12, text: 'Pub', parent_id: 11 },
  ] },
  { value: 13, text: 'House', parent_id: null, children: [
    { value: 15, text: 'Illumination', parent_id: 13 },
    { value: 16, text: 'Internet', parent_id: 13 },
    { value: 32, text: 'Rent', parent_id: 13 },
    { value: 33, text: 'Phone', parent_id: 13 },
    { value: 34, text: 'Reforms', parent_id: 13, children: [
      { value: 39, text: 'Kitchen', parent_id: 36, children: [
        { value: 40, text: 'Furniture', parent_id: 39 },
        { value: 41, text: 'Construction Materials', parent_id: 39 },
      ] },
    ] },
    { value: 36, text: 'Appliances', parent_id: 13 },
    { value: 38, text: 'Water', parent_id: 13 },
  ] },
  { value: 18, text: 'Pets', parent_id: null },
  { value: 19, text: 'Award', parent_id: null },
  { value: 20, text: 'Gifts', parent_id: null },
  { value: 21, text: 'Salary', parent_id: null },
  { value: 22, text: 'Health', parent_id: null, children: [
    { value: 23, text: 'Doctor', parent_id: 22 },
    { value: 24, text: 'Pharmacy', parent_id: 22 },
  ] },
  { value: 25, text: 'Transport', parent_id: null },
  { value: 26, text: 'Trip', parent_id: null, children: [
    { value: 27, text: 'NY', parent_id: 26},
  ] },
]

I created the following function:

cascateCategories(state) {
      var end = [];
      getNestedChildren(state.categories)
      return end

      function getNestedChildren(categories) {
        for(let i in categories) {
          
          categories.forEach(category => {
            if(category.value == categories[i].parent_id) {
              
              if(!category.children) {
                category['children'] = [];
              }
              
              category.children.push(categories[i]);
              end.push(category)             
            }
          });          
          console.log(end);
        }
        return end;
      }
    },

However, he adds the same item several times, not just 1. In addition, he disregards items that do not have children. At the end of the day, I have a problem with the code and I don’t know which one.

I am working with VueJS, Vuex and JavaScript.

Source: Ask Javascript Questions

LEAVE A COMMENT