Transform group data from JSON format into a suitable structure for displaying a Donut chart

This is a question about creating a Highcharts Donut chart that includes multiple series.

In this scenario, I have dynamic key properties xData and yData from a JSON input data model:

  xData= ["Phase", "Step", "Task"];
  yData = ["VPhase", "VStep", "VTask"]

  inputArray = [
    { Phase: "Phase 1", VPhase: 100, Step: "Step 1", VStep:50, Task: "Task 1", VTask: 20 },
    { Phase: "Phase 1", VPhase: 100, Step: "Step 1", VStep:50, Task: "Task 2", VTask: 30 },
    { Phase: "Phase 1", VPhase: 100, Step: "Step 2", VStep:50, Task: "Task 1", VTask: 25 },
    { Phase: "Phase 1", VPhase: 100, Step: "Step 2", VStep:50, Task: "Task 2", VTask: 25 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 1", VStep:100,Task: "Task 1", VTask: 60 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 1", VStep:100,Task: "Task 2", VTask: 40 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 2", VStep:50, Task: "Task 1", VTask: 15 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 2", VStep:50, Task: "Task 2", VTask: 35 }
  ];

I am looking to group and extract distinct consecutive index values from xData and yData in order to create an output array similar to the following structure:

outputArray = [
    {
      Phase: ["Phase 1", "Phase 2"],
      VPhase: [100, 150]
    },
    {
      Step: ["Step 1", "Step 2", "Step 1", "Step 2"],
      VStep: [50, 50, 100 ,50]
    },
    {
      Task: ["Task 1", "Task 2", "Task 1", "Task 2", "Task 1", "Task 2", "Task 1", "Task 2"],
      VTask: [20, 30, 25, 25, 60, 40, 15, 35]
    }
  ];

https://i.sstatic.net/NG7vv.png

Answer №1

After dedicating some time to the task, I managed to come up with the following solution:

const inputArray = [
    { Phase: "Phase 1", VPhase: 100, Step: "Step 1", VStep:50, Task: "Task 1", VTask: 20 },
    { Phase: "Phase 1", VPhase: 100, Step: "Step 1", VStep:50, Task: "Task 2", VTask: 30 },
    { Phase: "Phase 1", VPhase: 100, Step: "Step 2", VStep:50, Task: "Task 1", VTask: 25 },
    { Phase: "Phase 1", VPhase: 100, Step: "Step 2", VStep:50, Task: "Task 2", VTask: 25 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 1", VStep:100,Task: "Task 1", VTask: 60 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 1", VStep:100,Task: "Task 2", VTask: 40 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 2", VStep:50, Task: "Task 1", VTask: 15 },
    { Phase: "Phase 2", VPhase: 150, Step: "Step 2", VStep:50, Task: "Task 2", VTask: 35 }
  ];

function getGroupedData(data, firsts, seconds) {
    const reduced = data.reduce(function(m, d) {
      if(!m) m = {};
      firsts.forEach(function(key) {        
        if(!m[key]) m[key] = [];
        m[key].push(d[key]);
      });

      seconds.forEach(function(key) {
        if(!m[key]) m[key] = [];
        m[key].push(d[key]);
      });

      
      return m;      
    }, {});

    const obj = [];
    for(var i in firsts){
      const o = {};
      o[firsts[i]] = reduced[firsts[i]]
      o[seconds[i]] = reduced[seconds[i]]
      obj.push(o);
    }

    const final = [];
    obj.forEach(c=>{
      var keys = Object.keys(c);
      for(var i in c[keys[0]]){
        const o = {};
        o[keys[0]] = c[keys[0]][i];
        o[keys[1]] = c[keys[1]][i];
        if(!final.some(p => p[keys[0]] == c[keys[0]][i] && p[keys[1]] == c[keys[1]][i]))
          final.push(o);
      }
    })

    const output = [];
    for(var i in firsts){
      const o = {};
      o[firsts[i]] = [];
      o[seconds[i]] = [];
      final.forEach(c=>{
        if(c[firsts[i]]){
          o[firsts[i]].push(c[firsts[i]]);
          o[seconds[i]].push(c[seconds[i]]);
        }
      })
      output.push(o);
    }

    console.log(output);
}

getGroupedData(inputArray, ["Phase", "Step", "Task"], ["VPhase", "VStep", "VTask"]);




  

https://stackblitz.com/edit/typescript-vryxjl

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Please input a number in the designated field and specify the step interval without factoring in the value

Imagine a scenario where there is a textbox, and when the user clicks the up arrow, the value in the textbox should increase by 10. To elaborate further, if the initial value in the textbox is 12, pressing the up arrow should change it to 22. Subsequently, ...

What is the best method for sending a DbGeography parameter to MVC?

I am working on developing an API that allows users to save polygons on the server using ASP.NET MVC 5. Can anyone guide me on how to properly format the AJAX parameters for posting requests with DbGeography? This is what I have tried so far: $.ajax({ ...

Calculating the mean value of a multidimensional array that has been sorted in JavaScript

Check out the structure of my JSON File below. { "questions": ["Question1", "Question2"], "orgs": ["Org1", "Org2", "Org3"], "dates": ["Q1", "Q2", "Q3"], "values": [ [ [5, 88, 18], [50, 83, 10], ...

Looking to place a global filter outside the primeNG table component?

I am currently utilizing primeNG in my project and I have a need to incorporate a global filter. The challenge I am facing is that I must add this filter in a different component. These two components are deeply nested within other components. My approach ...

Determine the dynamic total value using AngularJS

My JSON object contains a list of products [ { "id": 22565423428, "title": "SV 8GB USB Flash Memory E100", "imageUrl": "/images/22565423428.png", "url": "/products/22565423428", "prices": [ { "amount": 159.92, " ...

Having difficulties with ng-repeat function in a table

This is the Angular code snippet I am currently working with: $scope.receipts = { acquirer : [ { id: 1, name: "test", balanceAmount: 4462.29, cardProducts: [ { ...

Insert this HTML table along with radio buttons into an Excel spreadsheet

My HTML table contains rows with a variety of content, including plain text characters and elements like radio buttons and lists. I want users to be able to copy-paste the table into MS Excel as plain text and have the radio button values replaced with "c ...

Save a Unique Number Format from the Initial JSON Data

Currently, I am using Oracle Apex 22.2 along with Oracle Database XE 21c on CentOS7 to traverse all nested elements of JSON data. However, I encountered an issue where the number values lose their original format. For example, instead of retaining 100.0, I ...

Converting a JavaScript object to JSON within Node-RED

I am attempting to convert a JavaScript object created in my Node-RED flow to JSON format, but I am struggling to figure out how to do it. The object consists of an hour and minute displayed on the screen, such as "13:02". I need to see this in JSON format ...

How can I fetch a value from a database and set it as the selected option in a

I am facing an issue with the usage of the selectpicker plugin from Bootstrap in order to select multiple items. My requirement is to create a modal for editing where the data is fetched from previous records, particularly an array. I am looking for a way ...

Struggling with the youtube API on slow network connection

Within my web project, I have integrated a YouTube player within a Bootstrap carousel slide that is part of a larger template (the code snippet below does not include the full html for the carousel): <script type="text/html> <div class="video-con ...

Refresh the dropdown menu selection to the default option

My HTML dropdown menu includes a default option along with dynamically generated options using ng-options. The variable dropdown is bound to the dynamic options, not the default one. <td> <select ng-model="dropdown" ng-options="item as item.n ...

I'm experiencing an "existing database with different casing already exists" error, even though I have no intention of creating a new database

My goal is to include a new word in a database called "wordsDb" within a collection named "wordsCollection": dbName = "wordsDb"; collectionName = "wordsCollection"; connectionUri = //... (secret) async add(word) { try { ...

"Enhance Your Dataset in chart.js 2.0 with an Exciting New Property

Need assistance in adding a property to dataset/label for identification on click. Previous attempts include: Chart.controllers.customBar = Chart.controllers.bar.extend({ code: null }); Progress has been made as the new property "code" is vis ...

Validating radio buttons in JS after submitting a form using PHP $_POST

I am dealing with a form that contains a variable number of radio buttons: <input id='create' name="post[]" type="radio" value="<? echo $newphrase; ?>" /> My goal is to validate the form to ensure that at least one button is select ...

"Encountering an error: invalid CSRF token in Node.js csurf

I have been utilizing the npm module csurf to generate a token. Initially, I retrieve the token from the server and then utilize it for the /register request. When I replicate these steps in Postman, everything seems to function correctly, but unfortunatel ...

What is the best way to swap the (-,+) symbol using a button in a Bootstrap Accordion?

Recently, I developed a bootstrap 4 accordion menu that displays a collapsible and expandable symbol. The symbol changes dynamically based on the collapse state. To achieve this effect, I utilized the :after pseudo-element. However, I now want to replace ...

Ways to retrieve particular items/properties from the JSON response string

Is there a way to extract and display only the first 3 items from my JSON data instead of the entire string? Below is the code I am currently using to loop through and display my records: <tr v-for="(list) in myData" v-bind:key="list.ema ...

tips for converting an object in typescript

import { Enseignant } from "./Enseignant"; import { AlreadyExistsError } from "./errors/AlreadyExistsError"; import { Etudiant } from "./Etudiant"; export class Utilisateur { private _id: string; private _first_name: string; private _last_name: stri ...