Home > Software engineering >  How to fill in missing values in a reduce function
How to fill in missing values in a reduce function

Time:11-14

I'm trying to create a stacked bar graph where I count the categories per month

The data coming from the backend is similar to this:

[
    {date: 'January', category: 'A'},
    {date: 'January', category: 'B'},
    {date: 'February', category: 'A'},
    {date: 'February', category: 'B'},
    {date: 'February', category: 'B'},
    {date: 'March', category: 'C'},
    {date: 'March', category: 'A'},
    {date: 'April', category: 'C'},
    ...
]

With help, I've managed to count the different categories and group the data into their respective months like the shape below:

[
    {date: 'January', countA: 1, countB: 1, countC: 0},
    {date: 'February', countA: 1, countB: 2, countC: 0},
    {date: 'March', countA: 1, countB: 0, countC: 1},
    ...
]

However, this only produces the data whenever the month exists. So if there is no data for the month of, say, June, there won't be any object with the name: 'June'.

I need to have these missing values filled with the corresponding month and with the count values to zeros

CodePudding user response:

Once data is ready with missing months only, fill in missing entries with Array.map

const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

const dataWithMissingMonths = [    {date: 'January', countA: 1, countB: 1, countC: 0},    {date: 'February', countA: 1, countB: 2, countC: 0},    {date: 'March', countA: 1, countB: 0, countC: 1} ];

const result = months.map(m => dataWithMissingMonths.find(data => data.date === m)?? {date: m, countA: 0, countB: 0, countC: 0});

console.log(result);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Here is an approach that is pretty straightforward, using forEach.

More on forEach here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

let months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
let cleanData =[];
let dirtyData = [];

// get original data
dirtyData = getData();

// iterate through each month
months.forEach(month => {
    let monthEntries = dirtyData.filter( e => e.date == month);
    let aCount = 0;
    let bCount = 0;
    let cCount = 0;

    // for each month, count how many enteries there were in each category
    monthEntries.forEach(e => {
        switch (e.category.toLowerCase()){
            case "a":
                aCount  ;
                break;
            case "b":
                bCount  ;
                break;
            case "c":
                cCount  ;
                break;
        }
    });

    // push the data to a new cleanData array in our preferred format
    cleanData.push({name: month, countA: aCount, countB: bCount, countC: cCount})
});

// log results
console.log(cleanData);

// function to retreive original data
function getData() { return [
    {date: 'January', category: 'A'},
    {date: 'January', category: 'B'},
    {date: 'February', category: 'A'},
    {date: 'February', category: 'B'},
    {date: 'February', category: 'C'},
    {date: 'March', category: 'B'},
    {date: 'March', category: 'A'},
    {date: 'March', category: 'B'},
    {date: 'March', category: 'C'},
    {date: 'March', category: 'B'},
    {date: 'April', category: 'A'},
    {date: 'April', category: 'B'},
    {date: 'April', category: 'C'},
    {date: 'April', category: 'B'},
    {date: 'May', category: 'A'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'C'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'A'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'C'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'A'},
    {date: 'May', category: 'B'},
    {date: 'June', category: 'C'},
    {date: 'June', category: 'B'},
    {date: 'June', category: 'A'},
    {date: 'July', category: 'B'},
    {date: 'July', category: 'C'},
    {date: 'July', category: 'B'},
    {date: 'July', category: 'A'},
    {date: 'July', category: 'B'},
    {date: 'August', category: 'C'},
    {date: 'September', category: 'B'},
    {date: 'September', category: 'A'},
    {date: 'September', category: 'B'},
    {date: 'October', category: 'C'},
    {date: 'October', category: 'B'},
    {date: 'October', category: 'A'},
    {date: 'October', category: 'B'},
    {date: 'November', category: 'C'},
    {date: 'November', category: 'A'},
    {date: 'December', category: 'B'},
    {date: 'December', category: 'B'},
];
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Here is an alternate implementation using reduce:

let arr = getData();
let res = Object.values(arr.reduce((acc, {date, category})=>{
      (acc[date] ??= {name: date, countA: 0, countB: 0, countC: 0})['count'   category];
    return acc;
}, {}));
console.log(res);


function getData() { return [
    {date: 'January', category: 'A'},
    {date: 'January', category: 'B'},
    {date: 'February', category: 'A'},
    {date: 'February', category: 'B'},
    {date: 'February', category: 'C'},
    {date: 'March', category: 'B'},
    {date: 'March', category: 'A'},
    {date: 'March', category: 'B'},
    {date: 'March', category: 'C'},
    {date: 'March', category: 'B'},
    {date: 'April', category: 'A'},
    {date: 'April', category: 'B'},
    {date: 'April', category: 'C'},
    {date: 'April', category: 'B'},
    {date: 'May', category: 'A'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'C'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'A'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'C'},
    {date: 'May', category: 'B'},
    {date: 'May', category: 'A'},
    {date: 'May', category: 'B'},
    {date: 'June', category: 'C'},
    {date: 'June', category: 'B'},
    {date: 'June', category: 'A'},
    {date: 'July', category: 'B'},
    {date: 'July', category: 'C'},
    {date: 'July', category: 'B'},
    {date: 'July', category: 'A'},
    {date: 'July', category: 'B'},
    {date: 'August', category: 'C'},
    {date: 'September', category: 'B'},
    {date: 'September', category: 'A'},
    {date: 'September', category: 'B'},
    {date: 'October', category: 'C'},
    {date: 'October', category: 'B'},
    {date: 'October', category: 'A'},
    {date: 'October', category: 'B'},
    {date: 'November', category: 'C'},
    {date: 'November', category: 'A'},
    {date: 'December', category: 'B'},
    {date: 'December', category: 'B'},
];
}
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related