'JSON data calculation and re-formate using Angular

I have a JSON file and I am trying to calculate the JSON file key based on the value and reformating it. My JSON file looks like below:

data=[
    {
        pet:'Cat',
        fruit:'Apple',
        fish:'Hilsha'
    },
    {
        pet:'Dog',
        fish:'Carp'
    },
    {
        pet:'Cat',
        fruit:'Orange',
        fish:'Lobster'
    }
];

I do like to calculate and formate it like below:

data=[
    {
        label:'Pet',
        total:3,
        list:[
            {
                name:'Cat',
                value: 2,
            },
            {
                name:'Dog',
                value: 1,
            }
        ]
    },
    {
        label:'Fruit',
        total:2,
        list:[
            {
                name:'Apple',
                value: 1,
            },
            {
                name:'Orange',
                value: 1,
            }
        ]
    },
    {
        label:'Fish',
        total:3,
        list:[
            {
                name:'Hilsha',
                value: 1,
            },
            {
                name:'Carp',
                value: 1,
            },
            {
                name:'Lobster',
                value: 1,
            }
        ]
    },
];

If anybody can help me, it will be very help for me and will save a day.



Solution 1:[1]

I have fixed this task myself. If I have any wrong, you can put your comment fill-free :)

``

ngOnInit(): void {
      this.dataService.$data.subscribe(data => {
         // Create new object and calculation according to category
         let petObj: any = {}
         let fruitObj: any = {}
         let fishObj: any = {}
         data.forEach((el: any) => {
            if (el.pet != undefined) {
               petObj[el.pet] = (petObj[el.pet] || 0) + 1;
            }
            if (el.fruit != undefined) {
               fruitObj[el.fruit] = (fruitObj[el.fruit] || 0) + 1;
            }
            if (el.fish != undefined) {
               fishObj[el.fish] = (fishObj[el.fish] || 0) + 1;
            }
         });

         // Create list according to category
         let pet_list: any = [];
         let fruit_list: any = [];
         let fish_list: any = [];
         for (var key in petObj) {
            let pet = {
               label: key,
               value: petObj[key]
            }
            pet_list.push(pet)
         }
         for (var key in fruitObj) {
            let fruit = {
               label: key,
               value: fruitObj[key]
            }
            fruit_list.push(fruit)
         }
         for (var key in fishObj) {
            let fish = {
               label: key,
               value: fishObj[key]
            }
            fish_list.push(fish)
         }

         // Calculate total sum according to category
         var totalPet = pet_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
         var totalFruit = fruit_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
         var totalFish = fish_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);

         // Rearrange the JSON
         this.rearrangeData = [
            {
               label: 'Pet',
               total: totalPet,
               list: pet_list
            },
            {
               label: 'Fruit',
               total: totalFruit,
               list: fruit_list
            },
            {
               label: 'Fish',
               total: totalFish,
               list: fish_list
            }
         ]
         console.log(this.rearrangeData)
         // End rearrange the JSON
      });
   }

``

Solution 2:[2]

You can simplify your function. Take a look this one

  group(oldData) {
    const data = [];  //declare an empty array

    oldData.forEach((x) => { 
                           //x will be {pet: 'Cat',fruit: 'Apple',fish: 'Hilsha'},
                          //          {pet: 'Dog',fish: 'Carp'}
                         //            ...
      Object.keys(x).forEach((key) => {  

                            //key will be 'pet','fruit',...
                       
        const item = data.find((d) => d.label == key); //search in the "data array"

        if (item) {      //if find it

          item.total++;  //add 1 to the property total of the element find it

                        // and search in the item.list the 'Cat'
          const list = item.list.find((l) => l.name == x[key]); 

                       //if find it add 1 to the property value of the list
          if (list) 
               list.value++;   
          else 
                      //if not, add to the list
                      //an object with property "name" and "value" equal 1

             item.list.push({ name: x[key], value: 1 });  
        } else
                 //if the element is not in the "array data"
                 //add an object with properties label, total and list
                 //see that list is an array with an unique element

          data.push({
            label: key,
            total: 1,
            list: [{ name: x[key], value: 1 }],
          });
      });
    });
    return data;
  }

You can use like

this.dataService.$data.subscribe(data => {
     this.rearrangeData=this.group(data)
}

NOTE: this function the labels are 'pet','fruit' and 'fish' not 'Pet', 'Fruit' and 'Fish'

Solution 3:[3]

Did you try reading the text leading up to this exercise? That'd be my first approach. After that, I'd use reduce. You can do pretty much anything with reduce.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Al Imran
Solution 2 Eliseo
Solution 3 Dave