Using Javascript, I am trying to convert some JSON data into the format used in Highcharts' basic line chart.
What I have to start with:
originalArray = [
['valueA', 1],
['valueA', 0],
['valueB', 9],
['valueB', 9],
['valueB', 3],
['valueC', 11]
]
And what I'm trying to create using the above:
desiredArray = [{
name: 'valueA',
data: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}, {
name: 'valueB',
data: [0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0]
}, {
name: 'valueC',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
}]
For some additional context, the 0-11 in originalArray[i][1]
references a month (0 = January), and the desiredArray
is a list of unique names and a count of their occurrences by month.
So far, I can:
originalArray
desiredArray
, and set the name
attribute data
attribute that contains an empty array But then I run into trouble, and can't figure out how to:
originalArray
originalArray
matches the name in the desiredArray
seriesArray[i].data
array, using the value of originalArray[i][1]
as the index (it always be 0-11). So I'm asking:
originalArray
, match up unique values, and then act only on those matches to push to the desiredArray
. desiredArray[i].data
I'm open to using libraries, such as underscore.js. Have been trying to figure this out for a couple of days now, so pretty much anything goes within the bounds of Javascript.
Updated with proper array initialization, now.
var max = originalArray.reduce(function(p,c){return Math.max(p,c[1]);},0);
var initSums = function(size) {
var arr = new Array(size);
for (var i=0;i<size;i++)
arr[i]=0;
return arr;
}
var map = originalArray.reduce(function(sums,val){
if (!sums.hasOwnProperty(val[0])) {
sums[val[0]] = initSums(max+1);
}
sums[val[0]][val[1]]++;
return sums;
},{});
var desiredArray = Object.keys(map).map(function(key) {
return {name: key, data: map[key]};
});
What we're doing here is a multi-step process:
Decide how big our arrays are going to need to be, by first scanning for the largest value in the original array.
Use an object to aggregate the counts (using Array.reduce()
).
Transform the object and its properties into an array of name/data pair objects (using Array.map
).
Edit : An improvement on S McCochran's solution, skipping the extraneous search for the maximum value in originalArray
, since there should always be 12 elements of each data array, one per month.
function formatForHighcharts(array) {
// Create a map from value name to array of month counts
var map = originalArray.reduce(function(sums, pair) {
var key = pair[0], val = pair[1];
if(!(key in sums))
sums[key] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// val is the month index, which corresponds directly to array index, so increase that
sums[key][val]++;
return sums;
}, {});
// Map the object to an array of { name: ..., data: ... } pairs
var formatted = Object.keys(map).map(function (key) {
return { name: key, data: map[key] };
});
return formatted;
}
Usage:
var desiredArray = formatForHighcharts(originalArray);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.