在JavaScript中创建任意长度的零填充数组最有效的方法是什么?
当前回答
var str = "0000000...0000";
var arr = str.split("");
表达式中的用法:arr[i]*1;
编辑:如果arr应该在整数表达式中使用,那么请不要介意字符值“0”。您只需按如下方式使用它:a=a*arr[i](假设a具有整数值)。
其他回答
如果使用ES6,则可以像这样使用Array.from():
Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
结果与相同
Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]
因为
Array.from({ length: 3 })
//[undefined, undefined, undefined]
这个concat版本在我的Chrome测试中要快得多(2013-03-21)。10000000个元素约200ms,而直接初始化为675。
function filledArray(len, value) {
if (len <= 0) return [];
var result = [value];
while (result.length < len/2) {
result = result.concat(result);
}
return result.concat(result.slice(0, len-result.length));
}
另外:如果你想用字符串填充数组,这是一种简洁的方法(虽然没有concat那么快):
function filledArrayString(len, value) {
return new Array(len+1).join(value).split('');
}
我知道我在某个地方有这个原型:)
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)。
截至ECMAScript2016,大型阵列有一个明确的选择。
由于这一答案在谷歌搜索中仍然排名靠前,所以这里有一个2017年的答案。
这里有一个当前的jsbench,其中有几十种流行的方法,包括迄今为止提出的许多方法。如果你找到更好的方法,请添加、分叉和分享。
我想指出,没有真正最有效的方法来创建任意长度的零填充数组。您可以优化速度,也可以优化清晰度和可维护性——根据项目的需要,两者都可以被视为更有效的选择。
在优化速度时,您需要:使用文字语法创建数组;设置长度,初始化迭代变量,并使用while循环遍历数组。这里有一个例子。
常量arr=[];arr.length=120000;设i=0;而(i<120000){arr[i]=0;i++;}
另一种可能的实施方式是:
(arr = []).length = n;
let i = 0;
while (i < n) {
arr[i] = 0;
i++;
}
但我强烈反对在实践中使用第二次植入,因为它不太清楚,也不允许在数组变量上保持块范围。
这比用for循环填充要快得多,比标准方法快90%左右
const arr = Array(n).fill(0);
但这种填充方法由于其清晰、简洁和可维护性,对于较小的阵列来说仍然是最有效的选择。除非您制作了大量长度为数千或更多的阵列,否则性能差异可能不会让您丧命。
其他一些重要的注意事项。大多数风格指南都建议您在使用ES6或更高版本时,如果没有非常特殊的原因,不要再使用var。对于不会被重新定义的变量使用const,对于会被重新定义变量使用let。MDN和Airbnb的风格指南是获取更多最佳实践信息的好地方。这些问题并不涉及语法,但重要的是,在搜索大量新旧答案时,熟悉JS的人必须了解这些新标准。
您可以检查索引是否存在,以便向其追加+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);