在JavaScript中创建任意长度的零填充数组最有效的方法是什么?


当前回答

我知道我在某个地方有这个原型:)

Array.prototype.init = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this[n] = x; }
    return this;
}

var a = (new Array(5)).init(0);

var b = [].init(0,4);

编辑:测试

作为对Joshua和其他方法的回应,我运行了自己的基准测试,我看到了与报告完全不同的结果。

以下是我测试的内容:

//my original method
Array.prototype.init = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this[n] = x; }
    return this;
}

//now using push which I had previously thought to be slower than direct assignment
Array.prototype.init2 = function(x,n)
{
    if(typeof(n)=='undefined') { n = this.length; }
    while (n--) { this.push(x); }
    return this;
}

//joshua's method
function newFilledArray(len, val) {
    var a = [];
    while(len--){
        a.push(val);
    }
    return a;
}

//test m1 and m2 with short arrays many times 10K * 10

var a = new Date();
for(var i=0; i<10000; i++)
{
    var t1 = [].init(0,10);
}
var A = new Date();

var b = new Date();
for(var i=0; i<10000; i++)
{
    var t2 = [].init2(0,10);
}
var B = new Date();

//test m1 and m2 with long array created once 100K

var c = new Date();
var t3 = [].init(0,100000);
var C = new Date();

var d = new Date();
var t4 = [].init2(0,100000);
var D = new Date();

//test m3 with short array many times 10K * 10

var e = new Date();
for(var i=0; i<10000; i++)
{
    var t5 = newFilledArray(10,0);
}
var E = new Date();

//test m3 with long array created once 100K

var f = new Date();
var t6 = newFilledArray(100000, 0)
var F = new Date();

结果:

IE7 deltas:
dA=156
dB=359
dC=125
dD=375
dE=468
dF=412

FF3.5 deltas:
dA=6
dB=13
dC=63
dD=8
dE=12
dF=8

因此,据我估计,总体而言,推送速度确实较慢,但在FF中使用较长的阵列时表现更好,但在IE中表现更差,这只是总体上很糟糕(quel surprise)。

其他回答

您可以检查索引是否存在,以便向其追加+1。

这样你就不需要一个填零的数组了。

例子:

var current_year = new Date().getFullYear();
var ages_array = new Array();

for (var i in data) {
    if(data[i]['BirthDate'] != null && data[i]['BirthDate'] != '0000-00-00'){

        var birth = new Date(data[i]['BirthDate']);
        var birth_year = birth.getFullYear();
        var age = current_year - birth_year;

        if(ages_array[age] == null){
            ages_array[age] = 1;
        }else{
            ages_array[age] += 1;
        }

    }
}

console.log(ages_array);
var str = "0000000...0000";
var arr = str.split("");

表达式中的用法:arr[i]*1;

编辑:如果arr应该在整数表达式中使用,那么请不要介意字符值“0”。您只需按如下方式使用它:a=a*arr[i](假设a具有整数值)。

其他人似乎缺少的是预先设置数组的长度,这样解释器就不会不断改变数组的大小。

我的简单一行代码是Array.protocol.slice.apply(newUint8Array(长度))

但是,如果我要创建一个函数来快速执行,而不需要一些复杂的变通方法,我可能会编写一个这样的函数:

var filledArray = function(value, l) {
    var i = 0, a = []; a.length = l;
    while(i<l) a[i++] = value;
    return a;
    }

在答案中没有看到这种方法,所以这里是:

"0".repeat( 200 ).split("").map( parseFloat )

结果,您将得到长度为200的零值数组:

[ 0, 0, 0, 0, ... 0 ]

我不确定这段代码的性能,但如果您将它用于相对较小的阵列,这应该不是问题。

值得指出的是,Array.prototype.fill是作为ECMAScript 6(Harmony)提案的一部分添加的。在考虑线程中提到的其他选项之前,我宁愿使用下面写的polyfill。

if (!Array.prototype.fill) {
  Array.prototype.fill = function(value) {

    // Steps 1-2.
    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    var O = Object(this);

    // Steps 3-5.
    var len = O.length >>> 0;

    // Steps 6-7.
    var start = arguments[1];
    var relativeStart = start >> 0;

    // Step 8.
    var k = relativeStart < 0 ?
      Math.max(len + relativeStart, 0) :
      Math.min(relativeStart, len);

    // Steps 9-10.
    var end = arguments[2];
    var relativeEnd = end === undefined ?
      len : end >> 0;

    // Step 11.
    var final = relativeEnd < 0 ?
      Math.max(len + relativeEnd, 0) :
      Math.min(relativeEnd, len);

    // Step 12.
    while (k < final) {
      O[k] = value;
      k++;
    }

    // Step 13.
    return O;
  };
}