Ori*_*iol 485
ES6介绍Array.prototype.fill
.它可以像这样使用:
new Array(len).fill(0);
Run Code Online (Sandbox Code Playgroud)
不确定它是否很快,但我喜欢它,因为它简短而且自我描述.
它仍然不在IE中(检查兼容性),但有一个polyfill可用.
zer*_*osh 377
虽然这是一个老线程,但我想加2美分.不确定这是多么缓慢/快速,但它是一个快速的单线.这是我做的:
如果我想预先填写一个数字:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)
如果我想预先填写字符串:
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
Run Code Online (Sandbox Code Playgroud)
其他答案建议:
new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
Run Code Online (Sandbox Code Playgroud)
但如果你想要0(数字)而不是"0"(字符串内为零),你可以这样做:
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)
Luc*_*iva 85
这是另一种使用ES6的方法,到目前为止还没有人提到过:
> Array.from(Array(3), () => 0)
< [0, 0, 0]
Run Code Online (Sandbox Code Playgroud)
它通过传递map函数作为第二个参数来工作Array.from
.
在上面的示例中,第一个参数分配一个由3个位置填充的数组,undefined
然后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]
Run Code Online (Sandbox Code Playgroud)
它比同等的更简洁(和优雅):
const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
numbers[i] = Math.round(10 * Math.random());
}
Run Code Online (Sandbox Code Playgroud)
此方法还可以通过利用回调中提供的索引参数来生成数字序列:
> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
repeat()
由于这个答案得到了很多关注,我也想展示这个很酷的技巧.虽然没有我主要答案那么有用,但是会介绍一些尚不为人知的但非常有用的String repeat()
方法.这是诀窍:
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Run Code Online (Sandbox Code Playgroud)
很酷,对吧?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]
Run Code Online (Sandbox Code Playgroud)
Ger*_*ncy 63
已经提到的ES 6填充方法很好地处理了这个问题.大多数现代桌面浏览器已经支持目前所需的阵列原型方法(Chromium,FF,Edge和Safari)[ 1 ].您可以在MDN上查找详细信息.一个简单的用法示例是
a = new Array(10).fill(0);
Run Code Online (Sandbox Code Playgroud)
鉴于当前的浏览器支持,除非您确定您的受众使用现代桌面浏览器,否则您应该谨慎使用它.
Kam*_*ski 57
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位).
下面我显示最快的浏览器(safari)的结果:
对于所有浏览器,最快的解决方案是M - 但它不是"典型阵列"(但非常快) - Safari 33.8k操作/秒,Chrome 5.2k,FF 3.5k,
典型阵列的最快解决方案:
最慢的解决方案:
解决方案N仅适用于Firefox和Chrome.
最快的:
最慢的:
n
Firefox)都是M let a = new Float32Array(n)
(但不是典型的阵列) - 因为它最快的浏览器是Safari(n
比Chrome 大6倍,比firefox快9倍)let a = Array(n).fill(0)
(快速和短代码) 您可以在此处对您的机器进行测试.
T.J*_*der 51
注释于2013年8月更新,2015年2月更新:2009年的答案与JavaScript的泛型Array
类型有关.它与ES2015中定义的新类型数组无关[现在在许多浏览器中都可用],Int32Array
等等.另请注意,ES2015 fill
为阵列和类型化数组添加了一种方法,这可能是填充它们的最有效方法......
此外,它可以为您创建阵列的一些实现带来很大的不同.特别是Chrome的V8引擎,如果认为可以使用高效,连续的内存阵列,只在必要时转移到基于对象的阵列.
对于大多数语言,它将是预分配,然后是零填充,如下所示:
function newFilledArray(len, val) {
var rv = new Array(len);
while (--len >= 0) {
rv[len] = val;
}
return rv;
}
Run Code Online (Sandbox Code Playgroud)
但是,JavaScript数组不是真正的数组,它们就像所有其他JavaScript对象一样是键/值映射,所以没有"预分配"要做(设置长度不分配那么多的插槽来填充),也没有是否有任何理由相信,当实现可能已经优化了它们对键的处理时,通过以相反的顺序添加键,不会超过倒数到零的好处(这只是为了使循环中的比较快速)与理论上的数组有关,你通常会按顺序执行它们.
实际上,Matthew Crumley指出,Firefox上的倒计时明显慢于计数,这是我可以确认的结果 - 它是数组的一部分(循环到零仍然比循环到var的极限更快).显然,以相反的顺序将元素添加到数组是Firefox的慢速操作.实际上,JavaScript实现的结果差别很大(这并不奇怪).这是一个快速而肮脏的测试页面(下面),用于浏览器实现(非常脏,在测试期间不会产生,因此提供最少的反馈并且将与脚本时间限制相冲突).我建议在测试之间刷新; 如果不这样做,FF(至少)会在重复测试时减慢速度.
使用Array#concat的相当复杂的版本比FF上的直接init更快,因为介于1,000和2,000个元素阵列之间.不过,在Chrome的V8引擎上,每次直接初始化胜出...
这是测试页面(实时复制):
<!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>
Run Code Online (Sandbox Code Playgroud)
dea*_*unk 35
默认情况下Uint8Array
,Uint16Array
和Uint32Array
阶级保持零作为它的值,所以你不需要任何复杂的充填技术,只是做:
var ary = new Uint8Array(10);
Run Code Online (Sandbox Code Playgroud)
ary
默认情况下,数组的所有元素都将为零.
fox*_*ris 27
如果使用ES6,可以像这样使用Array.from():
Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
Run Code Online (Sandbox Code Playgroud)
结果与...相同
Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]
Run Code Online (Sandbox Code Playgroud)
因为
Array.from({ length: 3 })
//[undefined, undefined, undefined]
Run Code Online (Sandbox Code Playgroud)
kan*_*gax 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']
Run Code Online (Sandbox Code Playgroud)
请注意,while
通常比更有效for-in
,forEach
等等.
Mat*_*ley 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;
}
Run Code Online (Sandbox Code Playgroud)
要么
function newFilledArray(length, val) {
var array = [];
var i = 0;
while (i < length) {
array[i++] = val;
}
return array;
}
Run Code Online (Sandbox Code Playgroud)
All*_*ice 18
使用对象表示法
var x = [];
Run Code Online (Sandbox Code Playgroud)
零填充?喜欢...
var x = [0,0,0,0,0,0];
Run Code Online (Sandbox Code Playgroud)
充满'未定义'......
var x = new Array(7);
Run Code Online (Sandbox Code Playgroud)
使用零的obj表示法
var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;
Run Code Online (Sandbox Code Playgroud)
作为旁注,如果你修改了Array的原型,两者都是
var x = new Array();
Run Code Online (Sandbox Code Playgroud)
和
var y = [];
Run Code Online (Sandbox Code Playgroud)
将有那些原型修改
无论如何,我不会过分关注这个操作的效率或速度,你可能会做的很多其他事情比实现包含零的任意长度数组更浪费和更昂贵.
аle*_*kyі 15
const arr = Array.from({ length: 10 }).fill(0);
console.log(arr)
Run Code Online (Sandbox Code Playgroud)
Eli*_*Eli 14
function zeroFilledArray(size) {
return new Array(size + 1).join('0').split('');
}
Run Code Online (Sandbox Code Playgroud)
Nen*_*vic 13
如果您需要的代码,我发现实现这一目标是创建一个零阵的最快方法的执行过程中创建不同长度的许多零个填充阵列一次,使用的关于这一主题提到的方法之一,长度的您知道永远不会超过它,然后根据需要切片该数组.
例如(使用上面选择的答案中的函数初始化数组),创建一个长度为maxLength的零填充数组,作为需要零数组的代码可见的变量:
var zero = newFilledArray(maxLength, 0);
Run Code Online (Sandbox Code Playgroud)
现在,每次切片这个数组,你需要长度的零满阵requiredLength < 最大长度:
zero.slice(0, requiredLength);
Run Code Online (Sandbox Code Playgroud)
我在执行代码期间数千次创建零填充数组,这极大地加速了这个过程.
Sal*_*ali 11
我没有反对:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);
Run Code Online (Sandbox Code Playgroud)
由Zertosh建议,但在新的ES6阵列扩展允许您使用fill
方法本地执行此操作.现在IE边缘,Chrome和FF支持它,但检查兼容性表
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
Run Code Online (Sandbox Code Playgroud)
这给你: [1, 2, 3, 9, 9, 6]
dur*_*rum 10
我通常这样做的方式(并且速度惊人)正在使用Uint8Array
.例如,创建1M元素的零填充向量:
var zeroFilled = [].slice.apply(new Uint8Array(1000000))
Run Code Online (Sandbox Code Playgroud)
我是Linux用户并且一直为我工作,但是一旦使用Mac的朋友有一些非零元素.我以为他的机器出现故障,但仍然是我们发现修复它的最安全的方法:
var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000))
Run Code Online (Sandbox Code Playgroud)
编辑
Chrome 25.0.1364.160
Firefox 20.0
缺少最重要的测试(至少对我而言):Node.js测试.我怀疑它接近Chrome基准测试.
从ECMAScript2016开始,大型阵列有一个明显的选择.
由于这个答案仍然显示在谷歌搜索的顶部附近,这里是2017年的答案.
这是一个当前的jsbench,有几十种流行的方法,包括到目前为止在这个问题上提出的很多方法.如果您找到更好的方法,请添加,分叉和共享.
我想指出,没有真正最有效的方法来创建任意长度的零填充数组.您可以针对速度进行优化,或者为了清晰度和可维护性 - 根据项目的需要,可以将其视为更有效的选择.
在优化速度时,您需要:使用文字语法创建数组; 设置长度,初始化迭代变量,并使用while循环遍历数组.这是一个例子.
const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
arr[i] = 0;
i++;
}
Run Code Online (Sandbox Code Playgroud)
另一种可能的实现方式是:
(arr = []).length = n;
let i = 0;
while (i < n) {
arr[i] = 0;
i++;
}
Run Code Online (Sandbox Code Playgroud)
但我强烈反对在实践中使用第二次植入,因为它不太清楚,并且不允许你在数组变量上保持块范围.
这些比填充for循环快得多,比标准方法快约90%
const arr = Array(n).fill(0);
Run Code Online (Sandbox Code Playgroud)
但是这种填充方法仍然是小型阵列最有效的选择,因为它具有清晰,简洁和可维护性.性能差异可能不会杀死你,除非你制作了大量数千或更多的数组.
其他一些重要的说明.var
在使用ES6或更高版本时,大多数样式指南建议您在没有特殊原因的情况下不再使用.使用const
该不会被重新定义变量,let
变量即会.该MDN和Airbnb的风格指南是伟大的地方去的最佳实践的详细信息.这些问题不是关于语法的问题,但重要的是,在搜索新旧答案时,新手JS的人员应该了解这些新标准.
_.range(0, length - 1, 0);
Run Code Online (Sandbox Code Playgroud)
或者,如果您有一个数组存在,并且您想要一个长度相同的数组
array.map(_.constant(0));
Run Code Online (Sandbox Code Playgroud)
创建一个全新的阵列
new Array(arrayLength).fill(0);
Run Code Online (Sandbox Code Playgroud)
在现有数组的末尾添加一些值
[...existingArray, ...new Array(numberOfElementsToAdd).fill(0)]
new Array(arrayLength).fill(0);
Run Code Online (Sandbox Code Playgroud)
没有在答案中看到这种方法,所以这里是:
"0".repeat( 200 ).split("").map( parseFloat )
Run Code Online (Sandbox Code Playgroud)
结果你将获得长度为200的零值数组:
[ 0, 0, 0, 0, ... 0 ]
Run Code Online (Sandbox Code Playgroud)
我不确定这段代码的性能,但如果你将它用于相对较小的数组,它应该不是问题.
归档时间: |
|
查看次数: |
316073 次 |
最近记录: |