Javascript:填充数组之间的缺失值

时间:2014-01-18 05:37:10

标签: javascript 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轴不一定是数字,也可以是日期。希望一个或多个答案适合于此。

4 个答案:

答案 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}]