-2

Input:

const data = [
  {
    category: 'Techonology',
    subcategory: 'laptop',
    sale: 19000,
    profit: 909049,
  },
  {
    category: 'Furniture',
    subcategory: 'badge',
    sale: 2009900,
    profit: 699600,
  },
  {
    category: 'Techonology',
    subcategory: 'chair',
    sale: 30000,
    profit: 500,
  },
  {
    category: 'Furniture',
    subcategory: 'bed',
    sale: 400,
    profit: 200000,
  },
]

The output should look like this:

{
  "name": "data",
  "children": [
    {
      "name": "Techonology",
      "children": [
        {
          "name": "laptop",
          "children": [
            {
              "name": "sale",
              "value": 19000
            }
          ]
        },
        {
          "name": "chair",
          "children": [
            {
              "name": "sale",
              "value": 30000
            }
          ]
        }
      ]
    },
    {
      "name": "Furniture",
      "children": [
        {
          "name": "badge",
          "children": [
            {
              "name": "sale",
              "value": 2009900
            }
          ]
        },
        {
          "name": "bed",
          "children": [
            {
              "name": "sale",
              "value": 400
            }
          ]
        }
      ]
    }
  ]
}
pilchard
  • 12,414
  • 5
  • 11
  • 23

1 Answers1

0

I assume you get the data from some site with this structure already define and this cannot be changed. Another way I suggest you to change the structure you're getting to something more manageable.

Anyway, following your structure or not, when you need to build a tree you must work recursively, to get the deepest structure and define correctly what you need.

Keep in mind this:

  • In your structure, you only have a subcategory per item but you can have a lot of entries with the same parent category where the only change is the subcategory element, this is not too optimal.
  • Since the structure becomes already defined, I think is better to treat and reorder it before arming the tree structure
  • To get a full example, I modified your data structure adding two children elements, because some of "subcategories" you have does not appear there.

So, the structure I used was :

var data1 = [
  {
    category: 'Techonology',
    subcategory: 'laptop',
    sale: 19000,
    profit: 909049,
  },
  {
    category: 'badge',
    sale: 19000,
    profit: 909049,
  },

  {
    category: 'childrenchair',
    sale: 19000,
    profit: 909049,
  },
  {
    category: 'chair',
    subcategory: 'childrenchair',
    sale: 19000,
    profit: 909049,
  },
  {
    category: 'Furniture',
    subcategory: 'badge',
    sale: 2009900,
    profit: 699600,
  },
  {
    category: 'Techonology',
    subcategory: 'chair',
    sale: 30000,
    profit: 500,
  },
  {
    category: 'Furniture',
    subcategory: 'bed',
    sale: 400,
    profit: 200000,
  },
]

and the code below defines the tree structure:

// loops the data to get all subcategory elements, this is used to
// avoid unnecessary iterations.
allChildren = data1.map(item=> item.subcategory).filter(item => !!item);
// this map has the data with the structure we need
preparedData = new Map()
data1.forEach(item => {
    console.log(1, item.category, item.subcategory);
    const data = preparedData.get(item.category) ?? {children: []};
    data.isChildren = allChildren.includes(item.category);
    if(item.subcategory) data.children.push(item.subcategory);
    preparedData.set(item.category, Object.assign(item, data));
});


tree = [];
/**
 getChildren method is recursive, it will be called for each category or subcategory with children's (recursively)

*/
getChildren = item=> {
    const children = item.children.filter(item=> {
        if(!preparedData.has(item)) return;
        const data = preparedData.get(item);

        const {category: name, sale, profit} = data;
        subchildren = data.children.length ? getChildren(item) : [];
        return {name, sale, profit, children: subchildren};

    });
    return children;
};
// loop the data
preparedData.forEach(item=>{
    // it the item has the property isChildren as true, then is a subcategory and
    // is not necessary to check it in the first level of the tree

  
    if(item.isChildren) return;
    const {category: name, sale, profit} = item;
    children = item.children.length ? getChildren(item) : [];
    tree.push({name, sale, profit, children});
});

I checked this code in the devtools console and runs, you can copy and pasted it to check and then make the adjusts required

jircdeveloper
  • 424
  • 2
  • 17