[英]Javascript: fill missing values between arrays
我正在寻找一种高性能的方法来填充两个数组之间互斥的值。 此数据用于JS图表,该图表必须包含每个x值的条目。 一个例子可以更好地解释这个:
之前:
obj1 = [{x:1, y:1}, {x:3, y:2}];
obj2 = [{x:2, y:2}, {x:4, y:4}];
后:
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}];
我使用嵌套for循环来自己做这件事,但随着对象和条目数量的增加,墙壁时间变得无法接受。 在最终零填充到几千个条目的数据集中,墙壁时间超过10秒。
我已经看过一些JS库,比如jQuery和下划线,但是目前还不清楚它们是否具有更好的执行功能。
更新 :感谢所有回复。 我会尝试一下,并将表现最佳的一个作为答案。 关于x值的注释:它们不一定是单调增加的(obj1和2可以跳过x值,只要它们都这样做)。 x轴不一定是数字,也可以是日期。 希望一个或多个答案适合于此。
基本上创建所有值的哈希值,以及每个对象中所有值的哈希值。 然后使用'all'哈希中的哈希填充对象,该哈希在'individual'哈希中不存在
// 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 } );
}
}
}
添加另一个答案,假设您的数据已预先排序。 如果它没有预先排序,请对其进行排序,这将起作用。 它具有内存使用量极少的优点,速度非常快,完成后您的数据将被排序:
var maxX = Math.max(
obj1[ obj1.length-1 ].x
, obj2[ obj2.length-1 ].x
);
fill( obj1, maxX );
fill( obj2, maxX );
function fill( obj, max ){
for( var i=0; i<max; i++ ){
if( !obj[i] || ( obj[i].x !== i+1 ) ){
obj.splice( i, 0, { x:i+1, y:0 });
}
}
}
如何使用以下方法(使用伪代码)
1)将其转换为数组,其中x为索引。
var arr = [];
for each object in input_list
arr[object.x] = object.y
2)循环上面的数组并用零填充undefined
arr2 = arr.map -> return (typeof value !== 'undefined') value : 0
3)将数组转换回对象
result = arr2.map -> return { x : index, y: value }
PS:您可以通过组合步骤2和3来进一步优化它以保存另一个循环。
这是另一种方法。 尽可能使用本机实现的方法来提高性能。
var obj1 = [{x:1, y:1}, {x:3, y:2}];
var obj2 = [{x:2, y:2}, {x:4, y:4}];
// get the x values from each array
var xGetter = function(i) { return i.x; };
var obj1xs = obj1.map(xGetter);
var obj2xs = obj2.map(xGetter);
// get the joined array
var joined = obj1.concat(obj2);
// get all x values
var xs = joined.map(xGetter);
// get the min and max values of x from both arrays combined
var min = Math.min.apply(null, xs), max = Math.max.apply(null, xs), i = min;
// fill the missing x values with zero y value
if(min < max) {
while(i<=max) {
if(obj1xs.indexOf(i) === -1) obj1.push({x: i, y: 0});
if(obj2xs.indexOf(i) === -1) obj2.push({x: i, y: 0});
i++;
}
}
// sort the arrays
var mySorter = function(a, b) { return a.x - b.x; };
obj1 = obj1.sort(mySorter);
obj2 = obj2.sort(mySorter);
输出将是:
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}]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.