在JavaScript中创建任意长度的零填充数组最有效的方法是什么?
当前回答
这里最快的是
(arr = []).length = len; arr.fill(0);
其他回答
function makeArrayOf(value, length) {
var arr = [], i = length;
while (i--) {
arr[i] = value;
}
return arr;
}
makeArrayOf(0, 5); // [0, 0, 0, 0, 0]
makeArrayOf('x', 3); // ['x', 'x', 'x']
注意while通常比in、forEach等更有效。
简言之
最快的解决方案:
let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
最短(方便)的解决方案(小阵列慢3倍,大阵列慢一点(Firefox上最慢))
Array(n).fill(0)
细节
今天2020.06.09我在浏览器Chrome 83.0、Firefox 77.0和Safari 13.1上对macOS High Sierra 10.13.6进行测试。我测试了两个测试用例的所选解决方案
小数组-有10个元素-您可以在这里执行测试大阵列-具有1M个元素-您可以在这里执行测试
结论
基于新Array(n)+for(n)的解决方案是小型阵列和大型阵列的最快解决方案(Chrome除外,但仍非常快),建议作为快速跨浏览器解决方案基于新Float32Array(n)(I)的解决方案返回非典型数组(例如,您不能在其上调用push(..)),因此我不会将其结果与其他解决方案进行比较-但是,对于所有浏览器上的大型数组,此解决方案的速度比其他解决方案快10-20倍基于for(L,M,N,O)的解决方案对于小型阵列来说是快速的基于填充(B,C)的解决方案在Chrome和Safari上速度很快,但在Firefox上对于大型阵列的速度却慢得惊人。它们对于小型阵列来说是中速的基于Array.apply(P)的解决方案为大型阵列抛出错误函数P(n){return Array.apply(null,Array(n)).map(Number.pr原型.valueOf,0);}尝试{P(1000000);}捕获(e){console.error(e.message);}
代码和示例
以下代码显示了测量中使用的解决方案
函数A(n){return[…new Array(n)].fill(0);}函数B(n){返回新数组(n).fill(0);}函数C(n){return数组(n).fill(0);}函数D(n){return Array.from({length:n},()=>0);}函数E(n){return[…new Array(n)].map(x=>0);}//类型为的数组函数F(n){return Array.from(新Int32Array(n));}函数G(n){return Array.from(new Float32Array(n));}函数H(n){return Array.from(new Float64Array(n));//需要比float32多2倍的内存}函数I(n){返回新的Float32Array(n);//这不是典型的阵列}函数J(n){return[].slice.apply(new Float32Array(n));}//基于函数K(n){设a=[];a.长度=n;设i=0;而(i<n){a[i]=0;i++;}返回a;}函数L(n){设a=[];对于(设i=0;i<n;i++)a[i]=0;返回a;}函数M(n){设a=[];对于(设i=0;i<n;i++)a.push(0);返回a;}函数N(N){设a=新数组(n);对于(设i=0;i<n;++i)a[i]=0;返回a;}函数O(n){设a=新数组(n);对于(设i=n;i-;)a[i]=0;返回a;}//其他函数P(n){return Array.apply(null,Array(n)).map(Number.pr原型.valueOf,0);}函数Q(n){return“0”.repeat(n).split(“”).map(parseFloat);}函数R(n){返回新数组(n+1).join(“0”).split(“”).map(parseFloat)}// ---------//测试// ---------[A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R]。对于每个(F=>{设a=f(10);console.log(`${f.name}长度=${a.length},arr[0]=${a[0]},arr[9]=${a[9]}`)});此代码段仅显示使用过的代码
Chrome的示例结果:
虽然这是一个旧线程,但我想添加我的2美分。不知道这有多慢/快,但它是一个快速的单线。以下是我所做的:
如果我想预先填写数字:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
如果我想预先填充字符串:
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
其他答案表明:
new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
但如果您想要0(数字)而不是“0”(字符串中为零),则可以执行以下操作:
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
在答案中没有看到这种方法,所以这里是:
"0".repeat( 200 ).split("").map( parseFloat )
结果,您将得到长度为200的零值数组:
[ 0, 0, 0, 0, ... 0 ]
我不确定这段代码的性能,但如果您将它用于相对较小的阵列,这应该不是问题。
我已经测试了IE 6/7/8、Firefox 3.5、Chrome和Opera中预分配/不预分配、向上/向下计数和for/while循环的所有组合。
下面的功能在Firefox、Chrome和IE8中始终是最快的或非常接近的,并且不比Opera和IE6中最快的慢太多。在我看来,这也是最简单明了的。我发现了几个while循环版本稍快的浏览器,所以我也将其包括在内以供参考。
function newFilledArray(length, val) {
var array = [];
for (var i = 0; i < length; i++) {
array[i] = val;
}
return array;
}
or
function newFilledArray(length, val) {
var array = [];
var i = 0;
while (i < length) {
array[i++] = val;
}
return array;
}