I have an array of data like this:
var data = [
['a', 2010, 12], ['a', 2010, 20], ['a', 2011, 43], ['a', 2012, 25], ['a', 2012, 15],
['b', 2010, 40], ['b', 2012, 65], ['b', 2013, 20], ['b', 2013, 10], ['b', 2013, 15],
['c', 2010, 13], ['c', 2010, 17], ['c', 2011, 22], ['c', 2011, 32], ['c', 2011, 10], ['c', 2012, 45], ['c', 2013, 10], ['c', 2013, 20]
]
and each array data is [name, year, value].
What I want to do here is to add values when name and year are the same and then sort data by year and change the order by name, so I want to convert data to:
var newData = [
['a', 2010, 32], ['b', 2010, 40], ['c', 2010, 30],
['a', 2011, 43], ['c', 2011, 64]
['a', 2012, 40], ['b', 2012, 65], ['c', 2012, 45],
['b', 2013, 45], ['c', 2013, 30]
]
I am doing this by taking multiple steps:
// find names
var sortByName = [];
var nameArr = [];
var namesFound = {};
for(var i = 0; i < data.length; i++) {
if(namesFound[data[i][0]]) { continue; }
nameArr.push(data[i][0]);
namesFound[data[i][0]] = true;
}
// sort data by name by creating an array for each name (2D array to 3D array)
for (var i = 0; i < nameArr.length; i++) {
var result = data.filter(function(arr) {
return arr[0] == nameArr[i]
})
sortByName.push(result)
}
// add values with a same year
var newArr = sortByName.map(function(eachArr) {
var sumBySameYear = eachArr.reduce(function(acc, arr) {
if (acc.year === arr[1]) {
acc.result[acc.result.length - 1][2] += arr[2];
} else {
acc.result.push(arr);
acc.year = arr[1]
}
return acc
}, {result: [], year: null});
return sumBySameYear.result
});
// 3D array to 2D array
var multiToSingleArr = [].concat.apply([], newArr);
// then sort new data by year and keep the order of name
var newData = multiToSingleArr.slice().sort(function(a, b) {
return a[1] - b[1] || a[0].localeCompare(b[0]);
});
I definitely feel like I am taking unnecessary steps here, so how can I make this more concise?