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


当前回答

如果您需要在代码执行期间创建许多不同长度的零填充数组,我发现实现这一点的最快方法是使用本主题中提到的方法之一创建一次零数组,其长度永远不会超过,然后根据需要分割该数组。

例如(使用上面所选答案中的函数初始化数组),创建长度为maxLength的零填充数组,作为需要零数组的代码可见的变量:

var zero = newFilledArray(maxLength, 0);

现在,每当您需要长度为requiredLength<maxLength:

zero.slice(0, requiredLength);

在执行代码期间,我创建了数千次零填充数组,这大大加快了这个过程。

其他回答

使用对象表示法

var x = [];

零填充?喜欢

var x = [0,0,0,0,0,0];

填充了“undefined”。。。

var x = new Array(7);

带零的obj符号

var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;

作为补充说明,如果修改Array的原型

var x = new Array();

and

var y = [];

将对原型进行修改

无论如何,我不会过分关注这个操作的效率或速度,你可能会做很多其他事情,这些事情比安装一个包含零的任意长度数组更浪费和昂贵。

我最快的功能是:

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

var st = (new Date()).getTime();
newFilledArray(1000000, 0)
console.log((new Date()).getTime() - st); // returned 63, 65, 62 milliseconds

使用本机push和shift向数组中添加项比声明数组范围并引用每个项来设置其值快得多(大约10倍)。

fyi:在firebug(firefox扩展)中运行时,第一个循环一直在倒计时,我总是会得到更快的时间。

var a = [];
var len = 1000000;
var st = (new Date()).getTime();
while(len){
    a.push(0);
    len -= 1;
}
console.log((new Date()).getTime() - st); // returned 863, 894, 875 milliseconds
st = (new Date()).getTime();
len = 1000000;
a = [];
for(var i = 0; i < len; i++){
    a.push(0);
}
console.log((new Date()).getTime() - st); // returned 1155, 1179, 1163 milliseconds

我很想知道T.J.Crowder对此有何看法?:-)

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

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)。

匿名函数:

(function(n) { while(n-- && this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]

用for循环稍微短一点:

(function(n) { for(;n--;this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]

适用于任何对象,只需更改this.push()中的内容即可。

您甚至可以保存函数:

function fill(size, content) {
  for(;size--;this.push(content));
  return this;
}

使用以下方法调用:

var helloArray = fill.call([], 5, 'hello');
// => ['hello', 'hello', 'hello', 'hello', 'hello']

将元素添加到已存在的数组:

var helloWorldArray = fill.call(helloArray, 5, 'world');
// => ['hello', 'hello', 'hello', 'hello', 'hello', 'world', 'world', 'world', 'world', 'world']

性能:http://jsperf.com/zero-filled-array-creation/25

新的Array(51).join(“0”).split(“”)怎么样?