我正在寻找一种高性能的方法来填充两个数组之间互斥的值。此数据用于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轴不一定是数字,也可以是日期。希望一个或多个答案适合于此。
答案 0 :(得分:1)
基本上创建所有值的哈希值,以及每个对象中所有值的哈希值。然后使用所有'中的哈希填充对象。不会存在于个人'中的哈希值散列
// 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 } );
}
}
}
答案 1 :(得分: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 });
}
}
}
答案 2 :(得分: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步来进一步优化它以保存另一个循环。
答案 3 :(得分:-1)
这是另一种方法。尽可能使用本机实现的方法来提高性能。
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}]