Reputation: 113
Am trying to sum the number of tickets per month. the array I have:
[['tickets', 'month','year'], [1, "june",2016],[3, "june",2015],[1, "december",2015]]
The result I want :
[['year', 'june','december'], [2016,1,0],[2015,3,1]]
but I can't figure out how to do it with javascript. any help? thanks,
Upvotes: 0
Views: 144
Reputation: 386520
You could use a dynamic approach for an arbitrary count of month with a hash table as reference to the years.
var data = [['tickets', 'month', 'year'], [1, "june", 2016], [3, "june", 2015], [1, "december", 2015]],
columns = ['year', 'june', 'december'],
temp = data.slice(1).reduce(function (result, item) {
result[item[2]] = result[item[2]] || {};
result[item[2]][item[1]] = item[0];
return result;
}, {}),
result = Object.keys(temp).sort(function (a, b) { return b - a; }).map(function (year) {
return columns.map(function (month, i) {
return i ? temp[year][month] || 0 : +year;
});
});
result.unshift(columns);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 11116
You can actually get some pretty cool use out of ES6 features here (spread syntax and array destructuring)
The idea is to create an object containing your years/months/total tickets from your original data source, and then you can use that object to map the data into the structure you require, like so:
var data = [['tickets', 'month', 'year'], [1, "june", 2016], [3, "june", 2015], [1, "december", 2015]];
function mapTicketData(data) {
var dataMap = data.slice(1).reduce(function(results, current, index) {
var [tickets, month, year] = current;
if (results.months.indexOf(month) === -1) {
results.months.push(month);
}
if (results.years.indexOf(year) === -1) {
results.years.push(year);
}
if (!results[year]) {
results[year] = {};
}
if (!results[year][month]) {
results[year][month] = 0;
}
results[year][month] += tickets;
return results;
}, { months: [], years: [] });
return [['year', ...dataMap.months], ...dataMap.years.map(function(year) {
return [year].concat(dataMap.months.map(function(month) {
return dataMap[year][month] || 0;
}));
})
];
}
console.log(mapTicketData(data));
Upvotes: 0
Reputation: 1004
One possible approach to this: I'm grouping the dates into an object, creating a unique array of the months that have an entry, and then processing it into the array you want.
var inArray = [['tickets', 'month','year'], [1, "june",2016],[3, "june",2015],[1, "december",2015]]
var validMonths = {}
function dateReducer (acc, curr) {
var year = curr[2]
var month = curr[1]
var num = curr[0]
if (year === "year"){return acc}
validMonths[month] = 0 // build unique array of valid months
if (!acc[year]) {
acc[year] = {}
acc[year][month] = num
} else {
if (!acc[year][month]) {
acc[year][month] = num
} else {
acc[year][month] += num
}
}
return acc
}
var obj = inArray.reduce(dateReducer, {})
// This may be fine, depending on your needs
validMonths = Object.keys(validMonths)
var outArray = ["year"].concat(validMonths)
for (var year in obj) {
if (obj.hasOwnProperty(year)){
var subArray = [year]
validMonths.forEach(v => {
subArray.push(obj[year][v] || 0)
})
outArray.push(subArray)
}
}
console.log(outArray)
Upvotes: 1