创建零填充JavaScript数组的最有效方法?

时间:2009-08-18 18:11:29

标签: javascript arrays

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

43 个答案:

答案 0 :(得分:439)

ES6介绍Array.prototype.fill。它可以像这样使用:

new Array(len).fill(0);

不确定它是否很快,但我喜欢它,因为它很短并且自我描述。

它仍然不在IE(check compatibility)中,但有一个polyfill available

答案 1 :(得分:369)

虽然这是一个老线程,但我想加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]

答案 2 :(得分:74)

使用预先计算的值填充数组的优雅方法

这是另一种使用ES6的方法,到目前为止还没有人提到过:

> Array.from(Array(3), () => 0)
< [0, 0, 0]

它的工作原理是将map函数作为Array.from的第二个参数传递。

在上面的示例中,第一个参数分配一个由值undefined填充的3个位置的数组,然后lambda函数将每个位置映射到值0

虽然Array(len).fill(0)较短,但如果你需要先通过一些计算来填充数组,它就不起作用(我知道这个问题并没有要求它,但是很多人最终都在这里寻找这个)

例如,如果您需要一个包含10个随机数的数组:

> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]

它比同等的更简洁(和优雅):

const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
    numbers[i] = Math.round(10 * Math.random());
}

此方法还可以通过利用回调中提供的索引参数来生成数字序列:

> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

奖励答案:使用字符串repeat()

填充数组

由于这个答案得到了很多关注,我也想展示这个很酷的技巧。虽然没有我的主要答案那么有用,但是会介绍仍然不是很有名但非常有用的String repeat()方法。这就是诀窍:

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]

很酷,对吧? repeat()是一个非常有用的方法来创建一个字符串,它是原始字符串重复一定次数。之后,split()为我们创建了一个数组,然后map()为我们想要的值创建数组。分步说明:

> "?".repeat(10)
< "??????????"

> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]

答案 3 :(得分:60)

已经提到的ES 6填充方法很好地处理了这个问题。大多数现代桌面浏览器已经支持截至今天所需的数组原型方法(Chromium,FF,Edge和Safari)[1]。您可以在MDN上查找详细信息。一个简单的用法示例是

a = new Array(10).fill(0);

鉴于目前的浏览器支持,除非您确定您的受众使用现代桌面浏览器,否则您应谨慎使用此功能。

答案 4 :(得分:49)

Note于2013年8月更新,2015年2月更新:2009年的答案与JavaScript的通用Array类型有关。它与ES2015 [现在在许多浏览器中可用]中定义的较新的类型数组无关,如Int32Array等。另请注意,ES2015为Arraystyped arrays添加了fill方法,这可能是填充它们的最有效方法......

此外,它可以对某些实现如何创建数组产生重大影响。特别是Chrome的V8引擎,如果认为可以使用高效,连续的内存阵列,只在必要时转移到基于对象的阵列。


对于大多数语言,它将是预分配,然后是零填充,如下所示:

function newFilledArray(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}

但是,JavaScript数组aren't really arrays,它们就像所有其他JavaScript对象一样是键/值映射,所以没有“预分配”要做(设置长度没有' t分配那么多的插槽来填充),也没有任何理由相信倒数到零的好处(这只是为了使循环中的比较快速)不会超过以相反顺序添加键时实现可能已经优化了它们对与数组相关的键的处理,理论上你通常会按顺序执行它们。

事实上,Matthew Crumley指出,Firefox上的倒计时明显慢于计数,结果我可以确认 - 它是数组的一部分(循环到零仍然比循环到一个极限更快) VAR)。显然,以相反的顺序将元素添加到数组是Firefox的慢速操作。实际上,JavaScript实现的结果差别很大(这并不奇怪)。这是一个快速而肮脏的测试页面(下面),用于浏览器实现(非常脏,在测试期间不会产生,因此提供最小的反馈并且将与脚本时间限制相冲突)。我建议在测试之间刷新;如果不这样做,FF(至少)会在重复测试时减慢。

使用Array#concat的相当复杂的版本比FF上的直接init更快,因为介于1,000和2,000个元素阵列之间。但是,在Chrome的V8引擎上,每次直接初始化胜出......

这是测试页面(live copy):

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zero Init Test Page</title>
<style type='text/css'>
body {
    font-family:    sans-serif;
}
#log p {
    margin:     0;
    padding:    0;
}
.error {
    color:      red;
}
.winner {
    color:      green;
    font-weight:    bold;
}
</style>
<script type='text/javascript' src='prototype-1.6.0.3.js'></script>
<script type='text/javascript'>
var testdefs = {
    'downpre':  {
        total:  0,
        desc:   "Count down, pre-decrement",
        func:   makeWithCountDownPre
    },
    'downpost': {
        total:  0,
        desc:   "Count down, post-decrement",
        func:   makeWithCountDownPost
    },
    'up':       {
        total:  0,
        desc:   "Count up (normal)",
        func:   makeWithCountUp
    },
    'downandup':  {
        total:  0,
        desc:   "Count down (for loop) and up (for filling)",
        func:   makeWithCountDownArrayUp
    },
    'concat':   {
        total:  0,
        desc:   "Concat",
        func:   makeWithConcat
    }
};

document.observe('dom:loaded', function() {
    var markup, defname;

    markup = "";
    for (defname in testdefs) {
        markup +=
            "<div><input type='checkbox' id='chk_" + defname + "' checked>" +
            "<label for='chk_" + defname + "'>" + testdefs[defname].desc + "</label></div>";
    }
    $('checkboxes').update(markup);
    $('btnTest').observe('click', btnTestClick);
});

function epoch() {
    return (new Date()).getTime();
}

function btnTestClick() {

    // Clear log
    $('log').update('Testing...');

    // Show running
    $('btnTest').disabled = true;

    // Run after a pause while the browser updates display
    btnTestClickPart2.defer();
}
function btnTestClickPart2() {

    try {
        runTests();
    }
    catch (e) {
        log("Exception: " + e);
    }

    // Re-enable the button; we don't yheidl
    $('btnTest').disabled = false;
}

function runTests() {
    var start, time, counter, length, defname, def, results, a, invalid, lowest, s;

    // Get loops and length
    s = $F('txtLoops');
    runcount = parseInt(s);
    if (isNaN(runcount) || runcount <= 0) {
        log("Invalid loops value '" + s + "'");
        return;
    }
    s = $F('txtLength');
    length = parseInt(s);
    if (isNaN(length) || length <= 0) {
        log("Invalid length value '" + s + "'");
        return;
    }

    // Clear log
    $('log').update('');

    // Do it
    for (counter = 0; counter <= runcount; ++counter) {

        for (defname in testdefs) {
            def = testdefs[defname];
            if ($('chk_' + defname).checked) {
                start = epoch();
                a = def.func(length);
                time = epoch() - start;
                if (counter == 0) {
                    // Don't count (warm up), but do check the algorithm works
                    invalid = validateResult(a, length);
                    if (invalid) {
                        log("<span class='error'>FAILURE</span> with def " + defname + ": " + invalid);
                        return;
                    }
                }
                else {
                    // Count this one
                    log("#" + counter + ": " + def.desc + ": " + time + "ms");
                    def.total += time;
                }
            }
        }
    }

    for (defname in testdefs) {
        def = testdefs[defname];
        if ($('chk_' + defname).checked) {
            def.avg = def.total / runcount;
            if (typeof lowest != 'number' || lowest > def.avg) {
                lowest = def.avg;
            }
        }
    }

    results =
        "<p>Results:" +
        "<br>Length: " + length +
        "<br>Loops: " + runcount +
        "</p>";
    for (defname in testdefs) {
        def = testdefs[defname];
        if ($('chk_' + defname).checked) {
            results += "<p" + (lowest == def.avg ? " class='winner'" : "") + ">" + def.desc + ", average time: " + def.avg + "ms</p>";
        }
    }
    results += "<hr>";
    $('log').insert({top: results});
}

function validateResult(a, length) {
    var n;

    if (a.length != length) {
        return "Length is wrong";
    }
    for (n = length - 1; n >= 0; --n) {
        if (a[n] != 0) {
            return "Index " + n + " is not zero";
        }
    }
    return undefined;
}

function makeWithCountDownPre(len) {
    var a;

    a = new Array(len);
    while (--len >= 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountDownPost(len) {
    var a;

    a = new Array(len);
    while (len-- > 0) {
        a[len] = 0;
    }
    return a;
}

function makeWithCountUp(len) {
    var a, i;

    a = new Array(len);
    for (i = 0; i < len; ++i) {
        a[i] = 0;
    }
    return a;
}

function makeWithCountDownArrayUp(len) {
    var a, i;

    a = new Array(len);
    i = 0;
    while (--len >= 0) {
        a[i++] = 0;
    }
    return a;
}

function makeWithConcat(len) {
    var a, rem, currlen;

    if (len == 0) {
        return [];
    }
    a = [0];
    currlen = 1;
    while (currlen < len) {
        rem = len - currlen;
        if (rem < currlen) {
            a = a.concat(a.slice(0, rem));
        }
        else {
            a = a.concat(a);
        }
        currlen = a.length;
    }
    return a;
}

function log(msg) {
    $('log').appendChild(new Element('p').update(msg));
}
</script>
</head>
<body><div>
<label for='txtLength'>Length:</label><input type='text' id='txtLength' value='10000'>
<br><label for='txtLoops'>Loops:</label><input type='text' id='txtLoops' value='10'>
<div id='checkboxes'></div>
<br><input type='button' id='btnTest' value='Test'>
<hr>
<div id='log'></div>
</div></body>
</html>

答案 5 :(得分:33)

默认情况下Uint8ArrayUint16ArrayUint32Array类将零保留为其值,因此您不需要任何复杂的填充技术,只需执行以下操作:

var ary = new Uint8Array(10);

默认情况下,数组ary的所有元素都将为零。

答案 6 :(得分:29)

最短

Array(n).fill(0)

(16个字符),其中n是数组的大小


2018.10.28我从其他答案中对15个命题进行了性能比较。测试是在Mac OS X 10.13.6 High Sierra上的三种浏览器上完成的:Chrome 69.0.3497,Safari 12.0(13606.2.11)和Firefox 63.0(64位)。

n = 100000的结果

以下我显示了最快浏览器(Safari)的搜索结果:

enter image description here enter image description here

对于所有浏览器,最快的解决方案是 M -但是它不是“典型数组”(但速度非常快)-Safari 33.8k次/秒,Chrome 5.2k,FF 3.5k,

典型阵列的最快解决方案:

    Safari 5.5k和Chrome 1.1k(在Firefox A 0.1k, B上)的
  • A B (类似) 0.06k)
  • F (对于Firefox 0.6k)(在Safari 3.1k,Chrome 1.1k上)
  • 对于Chrome和Safari A,B,F ,结果已关闭

最慢的解决方案:

  • G (适用于Safari 0.02k和Firefox 0.04k(在Chrome 0.1k上)
  • D (Chrome 0.04k版)(在Safari 0.33k上,在Firefox 0.15k上)

解决方案 N 仅适用于Firefox和Chrome。

n = 10的结果

最快:

  • M 在Chrome 17.3M和Safari 13.3M(Firefox 4.7M)上最快
  • A,B 与Firefox 16.9M(Chrome 15.6M,Safari 3.5M)相似,并且运行速度最快

最慢:

  • O (对于Safari 0.35M)
  • K (对于Chrome 0.35M)
  • N (对于Firefox 0.31M)

结论

  • 在所有浏览器中(除Firefox上的小型n之外,最快的解决方案是 M let a = new Float32Array(n)(但不是典型的阵列)-为此,最快的浏览器是Safari(大n的速度比Chrome快6倍,比firefox快9倍)
  • 对于典型阵列,首选解决方案是 A let a = Array(n).fill(0)(快速和简短代码)

您可以在计算机here上进行测试。

答案 7 :(得分:26)

如果您使用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]

答案 8 :(得分:23)

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通常比for-inforEach等效率更高。

答案 9 :(得分:20)

我已经在IE 6/7/8,Firefox 3.5,Chrome和Opera中测试了预分配/非预分配,向上/向下计数和for / while循环的所有组合。

下面的功能在Firefox,Chrome和IE8中始终是最快或非常接近的,并且比Opera和IE 6中最快的速度慢得多。在我看来,它也是最简单和最清晰的。我找到了几个浏览器,其中while循环版本稍快一些,所以我也将它包括在内以供参考。

function newFilledArray(length, val) {
    var array = [];
    for (var i = 0; i < length; i++) {
        array[i] = val;
    }
    return array;
}

function newFilledArray(length, val) {
    var array = [];
    var i = 0;
    while (i < length) {
        array[i++] = val;
    }
    return array;
}

答案 10 :(得分:15)

使用对象表示法

var x = [];

零填充?像...

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

填充'undefined'......

var x = new Array(7);

用零标记符号

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

作为旁注,如果你修改了Array的原型,那么

var x = new Array();

var y = [];

将进行那些原型修改

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

答案 11 :(得分:14)

function zeroFilledArray(size) {
    return new Array(size + 1).join('0').split('');
}

答案 12 :(得分:13)

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

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

var zero = newFilledArray(maxLength, 0);

现在每当你需要一个零填充的长度数组 requiredLength &lt; 最大长度

zero.slice(0, requiredLength);

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

答案 13 :(得分:10)

我没有反对意见:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);
Zertosh建议

,但在new ES6数组扩展中,您可以使用fill方法本机执行此操作。现在IE边缘,Chrome和FF支持它,但检查compatibility table

new Array(3).fill(0)会给你[0, 0, 0]。您可以使用任何值填充数组,例如new Array(5).fill('abc')(甚至是对象和其他数组)。

最重要的是,您可以使用fill修改以前的数组:

arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5)  # what to fill, start, end

为您提供:[1, 2, 3, 9, 9, 6]

答案 14 :(得分:10)

我通常这样做的方式(而且速度惊人)正在使用Uint8Array。例如,创建1M元素的零填充向量:

  var zeroFilled = [].slice.apply(new Uint8Array(1000000))

我是Linux用户并且一直为我工作,但是一旦使用Mac的朋友有一些非零元素。我认为他的机器出现故障,但仍然是我们找到解决问题的最安全的方法:

  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 

<强>被修改

Chrome 25.0.1364.160

  1. Frederik Gottlieb - 6.43
  2. Sam Barnum - 4.83
  3. Eli - 3.68
  4. Joshua 2.91
  5. Mathew Crumley - 2.67
  6. bduran - 2.55
  7. Allen Rice - 2.11
  8. kangax - 0.68
  9. TJ。克劳德 - 0.67
  10. zertosh - ERROR
  11. Firefox 20.0

    1. Allen Rice - 1.85
    2. Joshua - 1.82
    3. Mathew Crumley - 1.79
    4. bduran - 1.37
    5. Frederik Gottlieb - 0.67
    6. Sam Barnum - 0.63
    7. Eli - 0.59
    8. kagax - 0.13
    9. TJ。克劳德 - 0.13
    10. zertosh - ERROR
    11. 缺少最重要的测试(至少对我而言):Node.js测试。我怀疑它接近Chrome基准测试。

答案 15 :(得分:8)

ECMAScript2016开始,大型数组有一个明显的选择。

由于这个答案仍然显示在谷歌搜索的顶部附近,这里是2017年的答案。

这里有一个当前的jsbench,其中包含几十种流行的方法,其中包括目前针对此问题提出的许多方法。如果您找到更好的方法,请添加,分叉和分享。

我想指出,没有真正最有效的方法来创建任意长度的零填充数组。您可以针对速度进行优化,或者为了清晰度和可维护性 - 根据项目的需要,可以将其视为更有效的选择。

在优化速度时,您需要:使用文字语法创建数组;设置长度,初始化迭代变量,并使用while循环遍历数组。这是一个例子。

&#13;
&#13;
const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
  arr[i] = 0;
  i++;
}
&#13;
&#13;
&#13;

另一种可能的实现方式是:

(arr = []).length = n;
let i = 0;
while (i < n) {
    arr[i] = 0;
    i++;
}

但是我强烈反对在实践中使用第二次植入,因为它不太清楚,并且不允许你在数组变量上保持块范围。

这些比填充for循环快得多,比标准方法

快约90%
const arr = Array(n).fill(0);

但是由于它的清晰度,简洁性和可维护性,这种填充方法仍然是小型阵列的最有效选择。性能差异可能不会杀死你,除非你制作了大量数千或更多的数组。

其他一些重要说明。在使用ES6或更高版本时,大多数样式指南建议您在没有特殊原因的情况下不再使用var。对于不会被重新定义的变量使用const,对将要使用的变量使用letMDNAirbnb's Style Guide是了解有关最佳做法的更多信息的好地方。这些问题并不是关于语法的,但重要的是,在搜索新旧答案时,新手JS了解这些新标准非常重要。

答案 16 :(得分:8)

ES6解决方案:

[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]

答案 17 :(得分:7)

使用lodashunderscore

_.range(0, length - 1, 0);

或者,如果您有一个数组存在,并且您想要一个长度相同的数组

array.map(_.constant(0));

答案 18 :(得分:5)

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

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

结果你会得到长度为零的零值数组:

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

我不确定此代码的性能,但如果将它用于相对较小的数组,则不应该成为问题。

答案 19 :(得分:5)

new Array(51).join('0').split('')怎么样?

答案 20 :(得分:4)

我正在测试T.J的好答案。 Crowder,并提出了一个基于concat解决方案的递归合并,该解决方案在Chrome中的测试中表现优异(我没有测试其他浏览器)。

function makeRec(len, acc) {
    if (acc == null) acc = [];
    if (len <= 1) return acc;
    var b = makeRec(len >> 1, [0]);
    b = b.concat(b);
    if (len & 1) b = b.concat([0]);
    return b;
},

使用makeRec(29)调用该方法。

答案 21 :(得分:4)

这个concat版本在我的Chrome测试中更快(2013-03-21)。 10,000,000个元素约为200毫秒,直接初始化为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));
}

Bonus:如果你想用字符串填充你的数组,这是一个简洁的方法(尽管不如concat那么快):

function filledArrayString(len, value) {
    return new Array(len+1).join(value).split('');
}

答案 22 :(得分:4)

我最快的功能是:

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.克劳德做到了吗? : - )

答案 23 :(得分:4)

循环代码最短

a=i=[];for(;i<100;)a[i++]=0;

edit:
for(a=i=[];i<100;)a[i++]=0;
or
for(a=[],i=100;i--;)a[i]=0;

Safe var version

var a=[],i=0;for(;i<100;)a[i++]=0;

edit:
for(var i=100,a=[];i--;)a[i]=0;

答案 24 :(得分:3)

可能值得指出的是,Array.prototype.fill已添加ECMAScript 6 (Harmony) proposal作为{{3}}的一部分。在考虑线程中提到的其他选项之前,我宁愿选择下面写的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;
  };
}

答案 25 :(得分:3)

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

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

编辑:测试

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

这是我测试的内容:

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

答案 26 :(得分:1)

匿名函数:

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

for-loop缩短了一点:

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

适用于任何Object,只需更改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

答案 27 :(得分:1)

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

我的简单单行将是Array.prototype.slice.apply(new Uint8Array(length))

但是如果我要创建一个函数来快速完成它而没有一些hacky解决方法,我可能会写一个这样的函数:

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

答案 28 :(得分:1)

const arr = Array.from({ length: 10 })

答案 29 :(得分:1)

我只是使用:

var arr = [10];
for (var i=0; i<=arr.length;arr[i] = i, i++);

答案 30 :(得分:1)

lodash

_.fill(array, value)

是一种干净且跨浏览器安全的方式来填充数组。

答案 31 :(得分:1)

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

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

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

答案 32 :(得分:0)

const item = 0
const arr = Array.from({length: 10}, () => item)

const item = 0
const arr = Array.from({length: 42}, () => item)
console.log('arr', arr)

答案 33 :(得分:0)

最快的是

(arr = []).length = len; arr.fill(0);

答案 34 :(得分:0)

let filled = [];
filled.length = 10;
filled.fill(0);

console.log(filled);

答案 35 :(得分:0)

要创建一个全新的阵列

new Array(arrayLength).fill(0);

要在现有数组的末尾添加一些值

[...existingArray, ...new Array(numberOfElementsToAdd).fill(0)]

示例

//**To create an all new Array**

console.log(new Array(5).fill(0));

//**To add some values at the end of an existing Array**

let existingArray = [1,2,3]

console.log([...existingArray, ...new Array(5).fill(0)]);

答案 36 :(得分:0)

递归解决方案

正如其他几个人所指出的那样,利用.concat()通常可以提供快速解决方案。这是一个简单的递归解决方案:

function zeroFill(len, a){
  return len <= (a || (a = [0])).length ?
    a.slice(0, len) :
    zeroFill(len, a.concat(a))
}

console.log(zeroFill(5));

一个通用的递归数组填充函数:

function fill(len, v){
  return len <= (v = [].concat(v, v)).length ?
    v.slice(0, len) : fill(len, v)
}

console.log(fill(5, 'abc'));

答案 37 :(得分:0)

最快的方法是使用forEach =)

(我们保持IE&lt; 9的向后兼容性)

var fillArray = Array.prototype.forEach
    ? function(arr, n) {
         arr.forEach(function(_, index) { arr[index] = n; });
         return arr;
      }
    : function(arr, n) {
         var len = arr.length;
         arr.length = 0;
         while(len--) arr.push(n);
         return arr;
      };

// test
fillArray([1,2,3], 'X'); // => ['X', 'X', 'X']

答案 38 :(得分:0)

总有phpjs解决方案,你可以在这里找到:

http://phpjs.org/functions/array_fill/

我不能代表该项目(创建一个反映php更强大功能的javascript函数库)作为一个整体,但我亲自从那里开始的一些功能就像一个冠军。

答案 39 :(得分:0)

您可以检查索引是否存在,以便为其附加+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);

答案 40 :(得分:0)

这里找到另一个不错的选项http://www.2ality.com/2013/11/initializing-arrays.html

function fillArrayWithNumbers(n) {
  var arr = Array.apply(null, Array(n));
  return arr.map(function (x, i) { return i });
}

答案 41 :(得分:-1)

我知道这不是问题的目的,但这是一个开箱即用的想法。为什么?我的CSci教授指出,“清除”零数据并没有什么神奇之处。因此,最有效的方法是完全不做!仅当数据需要初始条件为零(对于某些求和)时才执行此操作-对于大多数应用程序通常不是这种情况。

答案 42 :(得分:-5)

return Array( quantity ).fill(1).map( n => return n * Math.abs(~~(Math.random() * (1000 - 1 + 1)) + 1) );

一行。