I am looking for a high-performance way to zero-fill values that are mutually exclusive between two arrays. This data is for a JS chart that must have entries for every x-value. An example may explain this better:
Before:
obj1 = [{x:1, y:1}, {x:3, y:2}];
obj2 = [{x:2, y:2}, {x:4, y:4}];
After:
obj1 = [{x:1, y:1}, {x: 2, y:0}, {x:3, y:2}, {x:4, y:0}];
obj2 = [{x:1, y:0}, {x: 2, y:2}, {x:3, y:0}, {x:4, y:4}];
I used nested for loops to do this myself but as the number of objects & entries increases, wall time gets unacceptably high. In a dataset that ended up zero-filling to a few thousand entries total, wall time was over 10 seconds.
I've looked at some JS libraries such as jQuery and underscore but it's not clear they have better performing functions for this.
Update: Thanks for all the responses. I'll try them out and mark the best performing one as the answer. A note on the x values: They aren't necessarily monotonically increasing (obj1 & 2 can skip an x value as long as both of them do). The x-axis isn't necessarily numbers, it could be dates as well. Hopefully one or more of the answers are adaptable to this.
Basically create a hash of all the values, along with a hash of all the values in each object. Then fill the object with the hashes in the 'all' hash that don't exist in the 'individual' hash
// hash of unique x values
var xValues = {};
// store each distinct x value
walk( obj1, 'obj1' );
walk( obj2, 'obj2' );
// fill each array with missing values
fill( obj1, 'obj1' );
fill( obj2, 'obj2' );
function walk( obj, nm ){
xValues[ nm ] || ( xValues[ nm ] = {} );
xValues.all || ( xValues.all = {} );
for( var i=0, l=obj.length; i<l; i++ ){
xValues[ nm ][ obj[ i ].x ] = 1;
xValues.all [ obj[ i ].x ] = 1;
}
}
function fill( obj, nm ){
for( var key in xValues.all ){
if( !( key in xValues[ nm ] ) ){
obj.push( { x : key, y : 0 } );
}
}
}
How about the following approach (with pseudocode)
1) Convert it into a array with x being the index.
var arr = [];
for each object in input_list
arr[object.x] = object.y
2) Loop through the above array and fill undefined with zeros
arr2 = arr.map -> return (typeof value !== 'undefined') value : 0
3) Convert the array back into the object
result = arr2.map -> return { x : index, y: value }
PS: You can optimize it further by combining step 2 and 3 to save another loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With