[Chartjs]-Chart Js Data transformation using Javascript

1๐Ÿ‘

โœ…

My solution will create chartjs data with two steps first step I will create grouping data and template data.

  • Grouping data which contain each name and verticalName with his countOfKeywords.
  • Template data which contain chartjs data with 0 percentages

Second step I will get data from grouping and put it in the template.


Input

const array = [
    {
        name: 'Attrition',
        verticalName: 'BCM',
        countOfKeywords: 20,
    },
    {
        name: 'Others',
        verticalName: 'BCM',
        countOfKeywords: 26,
    },
    {
        name: 'Others',
        verticalName: 'CGLR',
        countOfKeywords: 24,
    },
    {
        name: 'Attrition',
        verticalName: 'NEW',
        countOfKeywords: 20,
    },
    {
        name: 'Others',
        verticalName: 'NEW',
        countOfKeywords: 1,
    },
];

After Grouping

{
  "BCM": {
    "sum": 46,
    "keywords": {
      "Attrition": 20,
      "Others": 26
    }
  },
  "CGLR": {
    "sum": 24,
    "keywords": {
      "Others": 24
    }
  },
  "NEW": {
    "sum": 21,
    "keywords": {
      "Attrition": 20,
      "Others": 1
    }
  }
}

Template

{
  "labels": [
    "BCM",
    "CGLR",
    "NEW"
  ],
  "datasets": [
    {
      "label": "Attrition",
      "data": [
        0,
        0,
        0
      ]
    },
    {
      "label": "Others",
      "data": [
        0,
        0,
        0
      ]
    }
  ]
}

Output

{
  "labels": [
    "BCM",
    "CGLR",
    "NEW"
  ],
  "datasets": [
    {
      "label": "Attrition",
      "data": [
        43.47826086956522,
        0,
        95.23809523809523
      ]
    },
    {
      "label": "Others",
      "data": [
        56.52173913043478,
        100,
        4.761904761904762
      ]
    }
  ]
}

Full code

// input
const array = [
    {
        name: 'Attrition',
        verticalName: 'BCM',
        countOfKeywords: 20,
    },
    {
        name: 'Others',
        verticalName: 'BCM',
        countOfKeywords: 26,
    },
    {
        name: 'Others',
        verticalName: 'CGLR',
        countOfKeywords: 24,
    },
    {
        name: 'Attrition',
        verticalName: 'NEW',
        countOfKeywords: 20,
    },
    {
        name: 'Others',
        verticalName: 'NEW',
        countOfKeywords: 1,
    },
];

// declare variables
let uniqueNames = new Set();
const grouping = {};
const template = {
    labels: [],
    datasets: []
}

// create grouping object and create template labels 
for (let i = 0; i < array.length; i += 1) {
    const element = array[i];

    if (grouping[element.verticalName] === undefined) {
        template.labels.push(element.verticalName);
        grouping[element.verticalName] = { sum: 0, keywords: {} };
    };

    grouping[element.verticalName].sum += element.countOfKeywords;
    grouping[element.verticalName].keywords[element.name] = grouping[element.verticalName].keywords[element.name] ? grouping[element.verticalName].keywords[element.name] + element.countOfKeywords : element.countOfKeywords

    uniqueNames.add(element.name);
}

// uniqueNames Set to Array   
uniqueNames = [...uniqueNames];

// create template datasets with 0 percentage
// I did it after first loop because I want to makesure the template.labels.length completed
template.datasets = uniqueNames.map(label => ({ label, data: new Array(template.labels.length).fill(0) }));

// target for now create grouping & create template with labels and 0 percentages
// console.log(JSON.stringify(grouping, null, 2));
// console.log(JSON.stringify(template, null, 2));

// calculate the percentages
for (let i = 0; i < template.datasets.length; i++) {
    const uniqueName = uniqueNames[i];

    for (let j = 0; j < template.labels.length; j++) {
        const label = template.labels[j];
        if (grouping[label].keywords[uniqueName] === undefined) {
            template.datasets[i].data[j] = 0;
        } else {
            template.datasets[i].data[j] = grouping[label].keywords[uniqueName] / grouping[label].sum * 100;
        }
    }
}

// output
console.log(JSON.stringify(template, null, 2));


UPDATE

More optimized code by skip add datasets to template before second loop

// input
const array = [
    {
        name: 'Attrition',
        verticalName: 'BCM',
        countOfKeywords: 20,
    },
    {
        name: 'Others',
        verticalName: 'BCM',
        countOfKeywords: 26,
    },
    {
        name: 'Others',
        verticalName: 'CGLR',
        countOfKeywords: 24,
    },
    {
        name: 'Attrition',
        verticalName: 'NEW',
        countOfKeywords: 20,
    },
    {
        name: 'Others',
        verticalName: 'NEW',
        countOfKeywords: 1,
    },
];

// declare variables
let uniqueNames = new Set();
const grouping = {};
const template = {
    labels: [],
    datasets: []
}

// create grouping object and create template labels 
for (let i = 0; i < array.length; i += 1) {
    const element = array[i];

    if (grouping[element.verticalName] === undefined) {
        template.labels.push(element.verticalName);
        grouping[element.verticalName] = { sum: 0, keywords: {} };
    };

    grouping[element.verticalName].sum += element.countOfKeywords;
    grouping[element.verticalName].keywords[element.name] = grouping[element.verticalName].keywords[element.name] ? grouping[element.verticalName].keywords[element.name] + element.countOfKeywords : element.countOfKeywords

    uniqueNames.add(element.name);
}

// uniqueNames Set to Array   
uniqueNames = [...uniqueNames];

// target for now create grouping & create template with labels and without datasets 
// console.log(JSON.stringify(grouping, null, 2));
// console.log(JSON.stringify(template, null, 2));
 
// add datasets
// calculate the percentages
for (let i = 0; i < uniqueNames.length; i++) {
    const uniqueName = uniqueNames[i];

    template.datasets.push({ label: uniqueName, data: [] })

    for (let j = 0; j < template.labels.length; j++) {
        const label = template.labels[j];
        if (grouping[label].keywords[uniqueName] === undefined) {
            template.datasets[i].data[j] = 0;
        } else {
            template.datasets[i].data[j] = grouping[label].keywords[uniqueName] / grouping[label].sum * 100;
        }
    }
}

// output
console.log(JSON.stringify(template, null, 2));

Leave a comment