Reputation: 1231
Is there a way how can i complete missing month and sale in an incomplete array.
sometimes i get a query like this:
var sales = [
{'month': '04', 'sale': 126},
{'month': '06', 'sale': 165},
{'month': '07', 'sale': 10},
{'month': '08', 'sale': 20},
{'month': '09', 'sale': 211},
{'month': '10', 'sale': 27},
{'month': '11', 'sale': 112},
];
and i need to add the missing months with sale: 0.
I thought i can make a second array with all months and then compare this two arrays and pick the duplicates to the array with all months:
var compareArray = [
{'month': '01', 'sale': 0},
{'month': '02', 'sale': 0},
{'month': '03', 'sale': 0},
{'month': '04', 'sale': 0},
{'month': '05', 'sale': 0},
{'month': '06', 'sale': 0},
{'month': '07', 'sale': 0},
{'month': '08', 'sale': 0},
{'month': '09', 'sale': 0},
{'month': '10', 'sale': 0},
{'month': '11', 'sale': 0},
{'month': '12', 'sale': 0},
];
Upvotes: 6
Views: 2106
Reputation: 350034
Instead of pre-defining the 12-entries array, you could use Array(12).keys()
and use Array.from
to map that to the desired output:
var sales = [{'month': '04', 'sale': 126}, {'month': '06', 'sale': 165}, {'month': '07', 'sale': 10}, {'month': '08', 'sale': 20}, {'month': '09', 'sale': 211}, {'month': '10', 'sale': 27}, {'month': '11', 'sale': 112}];
sales = Array.from(Array(12).keys(), month =>
sales.find(sale => +sale.month === month+1) || { month: ("0"+(month+1)).substr(-2), sale: 0 }
);
console.log(sales);
Edit in 2025: With the addition of iterator helper methods in ECMAScript 2025, this can be rewritten as a chain:
let sales = [{'month': '04', 'sale': 126}, {'month': '06', 'sale': 165}, {'month': '07', 'sale': 10}, {'month': '08', 'sale': 20}, {'month': '09', 'sale': 211}, {'month': '10', 'sale': 27}, {'month': '11', 'sale': 112}];
sales = Array(12).keys().map(month =>
sales.find(sale => +sale.month === ++month) ?? { month: ("0"+month).substr(-2), sale: 0 }
).toArray();
console.log(sales);
Upvotes: 9
Reputation: 5941
You can use the same approach I used below. Bascially just loop 1 - 12 and if you find missing months, add them to the array. Once you have all your months in the array, simply sort in ascending order based on month number.
const sales = [{
'month': '04',
'sale': 126
},
{
'month': '06',
'sale': 165
},
{
'month': '07',
'sale': 10
},
{
'month': '08',
'sale': 20
},
{
'month': '09',
'sale': 211
},
{
'month': '10',
'sale': 27
},
{
'month': '11',
'sale': 112
}
];
function generateSalesReport(salesData) {
const monthsWithSales = [];
const salesReport = [];
salesData.forEach(el => {
monthsWithSales.push(Number.parseInt(el.month));
salesReport.push(el);
});
//Fill in the missing months
for (let i = 1; i <= 12; i++) {
if (monthsWithSales.indexOf(i) === -1) {
let monthStr = i.toString();
salesReport.push({
'month': monthStr.length < 2 ? '0' + monthStr : monthStr,
'sale': 0
});
}
}
//Sort the sales report array
return salesReport.sort((a, b) => parseInt(a.month) - parseInt(b.month));
}
console.log(generateSalesReport(sales));
Upvotes: 0
Reputation: 20744
An approach based on .map and .find array methods
const data = [
{'month': '04', 'sale': 126},
{'month': '06', 'sale': 165},
{'month': '07', 'sale': 10},
{'month': '08', 'sale': 20},
{'month': '09', 'sale': 211},
{'month': '10', 'sale': 27},
{'month': '11', 'sale': 112},
];
const result = [...Array(12)].map((m, i) => {
const month = i < 9 ? '0' + (i + 1) : String(i + 1);
return data.find(d => d.month === month) || { month, sale: 0 };
});
Upvotes: 3
Reputation: 413702
Because your month numbers are numbers, and span a convenient range, you can use them as array indexes:
var yearSales = sales.reduce(function(rv, month) {
a[parseInt(month.month, 10)] = month;
return a;
}, []);
Then you can find the empty slots:
for (let i = 0; i < 12; i++)
if (!yearSales[i])
yearSales[i] = { month: i, sales: 0 };
(I didn't use .forEach()
because it skips empty slots, and those are the ones I want to target.)
Upvotes: 0
Reputation: 30739
You can use a simple for
loop then Array.sort()
to get the desired output:
var sales = [{
'month': '04',
'sale': 126
},
{
'month': '06',
'sale': 165
},
{
'month': '07',
'sale': 10
},
{
'month': '08',
'sale': 20
},
{
'month': '09',
'sale': 211
},
{
'month': '10',
'sale': 27
},
{
'month': '11',
'sale': 112
},
];
for (var i = 1; i <= 12; i++) {
var existObj = sales.find(item => +item.month === i);
if (!existObj) {
sales.push({
'month': i > 9 ? i : '0' + i,
'sale': 0
});
}
}
sales.sort(function(a, b) {
return +a.month - +b.month;
});
console.log(sales);
Upvotes: 0