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

[英]Most efficient way to create a zero filled JavaScript array?


What is the most efficient way to create an arbitrary length zero filled array in JavaScript?

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

36 个解决方案

#1


346  

Although this is an old thread, I wanted to add my 2 cents to it. Not sure how slow/fast this is, but it's a quick one liner. Here is what I do:

虽然这是一个旧的线程,我想增加我的2美分。不知道这有多慢,但它是一个快速的一行。以下是我的工作:

If I want to pre-fill with a number:

如果我想预先填写一个数字:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]

If I want to pre-fill with a string:

如果我想预先填充一个字符串:

Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]

Other answers have suggested:

其他答案建议:

new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]

but if you want 0 (the number) and not "0" (zero inside a string), you can do:

但是如果你想要0(数字)而不是“0”(在字符串中为0),你可以这样做:

new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]

#2


276  

ES6 introduces Array.prototype.fill. It can be used like this:

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

new Array(len).fill(0);

Not sure if it's fast, but I like it because it's short and self-describing.

不确定它是不是快,但我喜欢它,因为它是简短的和自我描述的。

#3


50  

The already mentioned ES 6 fill method takes care of this nicely. Most modern desktop browsers already support the required Array prototype methods as of today (Chromium, FF, Edge and Safari) [1]. You can look up details on MDN. A simple usage example is

已经提到的ES 6填充方法很好地解决了这个问题。大多数现代桌面浏览器已经支持了所需的数组原型方法[1]。你可以在MDN上查阅详细资料。一个简单的用法示例是。

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

Given the current browser support you should be cautious to use this unless you are sure your audience uses modern Desktop browsers.

考虑到当前的浏览器支持,您应该谨慎使用它,除非您确定您的受众使用的是现代桌面浏览器。

#4


47  

Note added August 2013, updated February 2015: The answer below from 2009 relates to JavaScript's generic Array type. It doesn't relate to the newer typed arrays defined in ES2015 [and available now in many browsers], like Int32Array and such. Also note that ES2015 adds a fill method to both Arrays and typed arrays, which is likely to be the most efficient way to fill them...

注:2013年8月,2015年2月更新:2009年的答案与JavaScript的通用数组类型有关。它与ES2015定义的新类型数组不相关(现在在许多浏览器中都可以使用),比如int32数组等。还要注意,ES2015为数组和类型化数组添加了填充方法,这可能是填充它们的最有效的方法。

Also, it can make a big difference to some implementations how you create the array. Chrome's V8 engine, in particular, tries to use a highly-efficient, contiguous-memory array if it thinks it can, shifting to the object-based array only when necessary.

此外,它还可以对一些实现如何创建数组产生很大的影响。特别是Chrome的V8引擎,如果它认为可以的话,它会尝试使用一个高效的、连续的内存数组,只在必要的时候才转向基于对象的数组。


With most languages, it would be pre-allocate, then zero-fill, like this:

对于大多数语言,它是预先分配的,然后是零填充,像这样:

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

But, JavaScript arrays aren't really arrays, they're key/value maps just like all other JavaScript objects, so there's no "pre-allocate" to do (setting the length doesn't allocate that many slots to fill), nor is there any reason to believe that the benefit of counting down to zero (which is just to make the comparison in the loop fast) isn't outweighed by adding the keys in reverse order when the implementation may well have optimized their handling of the keys related to arrays on the theory you'll generally do them in order.

但JavaScript数组不是数组,它们键/值地图就像所有其他的JavaScript对象,所以没有“预先分配”(设置长度不分配,许多槽填满),也没有任何理由相信倒计时的利益为零(也就是循环中的比较快)不超过通过添加键在相反的顺序实现可能优化处理数组键相关的理论你通常做他们。

In fact, Matthew Crumley pointed out that counting down is markedly slower on Firefox than counting up, a result I can confirm — it's the array part of it (looping down to zero is still faster than looping up to a limit in a var). Apparently adding the elements to the array in reverse order is a slow op on Firefox. In fact, the results vary quite a bit by JavaScript implementation (which isn't all that surprising). Here's a quick and dirty test page (below) for browser implementations (very dirty, doesn't yield during tests, so provides minimal feedback and will run afoul of script time limits). I recommend refreshing between tests; FF (at least) slows down on repeated tests if you don't.

事实上,Matthew Crumley指出,在Firefox中计数比计算要慢得多,这是我可以确定的结果,它是数组的一部分(循环到0的速度比在var中循环到一个极限还要快)。显然,以相反的顺序将元素添加到数组中是Firefox的一个慢操作。实际上,JavaScript实现的结果相差很大(这并不令人惊讶)。对于浏览器实现来说,下面是一个快速而又脏的测试页面(非常脏,在测试中不产生效果,因此提供了最少的反馈,并且会与脚本的时间限制相冲突)。我建议在测试之间刷新;如果没有的话,FF(至少)会慢下来。

The fairly complicated version that uses Array#concat is faster than a straight init on FF as of somewhere between 1,000 and 2,000 element arrays. On Chrome's V8 engine, though, straight init wins out every time...

使用数组#concat的相当复杂的版本比在1,000到2,000个元素数组之间的FF上的直接init要快。不过,在Chrome的V8引擎上,每次都能胜出。

Here's the test page (live copy):

这是测试页面(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


45  

Elegant way to fill an array with precomputed values

Here is another way to do it using ES6 that nobody has mentioned so far:

下面是另一种使用ES6的方法,没有人提到过:

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

It works by passing a map function as the second parameter of Array.from.

它通过将map函数传递为Array.from的第二个参数来工作。

In the example above, the first parameter allocates an array of 3 positions filled with the value undefined and then the lambda function maps each one of them to the value 0.

在上面的示例中,第一个参数分配了一个3个位置的数组,其中包含了未定义的值,然后lambda函数将每个值映射到值0。

Although Array(len).fill(0) is shorter, it doesn't work if you need to fill the array by doing some computation first (I know the question didn't ask for it, but a lot of people end up here looking for this).

虽然Array(len).fill(0)比较短,但是如果您需要先进行一些计算(我知道这个问题并没有要求它,但是很多人在这里寻找这个),那么它就不工作了。

For instance, if you need an array with 10 random numbers:

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

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

It's more concise (and elegant) than the equivalent:

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

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

This method can also be used to generate sequences of numbers by taking advantage of the index parameter provided in the callback:

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

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

Bonus answer: fill an array using String repeat()

Since this answer is getting a good deal of attention, I also wanted to show this cool trick. Although not as useful as my main answer, will introduce the still not very known, but very useful String repeat() method. Here's the trick:

因为这个答案得到了很多的关注,我也想展示这个很酷的技巧。虽然没有我的主要回答有用,但将介绍仍然不太为人所知的,但非常有用的字符串repeat()方法。关键之处在于:

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

Cool, huh? repeat() is a very useful method to create a string that is the repetition of the original string a certain number of times. After that, split() creates an array for us, which is then map()ped to the values we want. Breaking it down in steps:

酷,不是吗?repeat()是创建字符串的一个非常有用的方法,它是原始字符串的重复次数。之后,split()为我们创建一个数组,然后将它映射到我们想要的值。把它分解成几个步骤:

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

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

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

#6


31  

By default Uint8Array, Uint16Array and Uint32Array classes keep zeros as its values, so you don't need any complex filling techniques, just do:

默认情况下,Uint8Array、Uint16Array和Uint32Array类都将0作为其值,因此您不需要任何复杂的填充技术,只需这样做:

var ary = new Uint8Array(10);

all elements of array ary will be zeros by default.

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

#7


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']

Note that while is usually more efficient than for-in, forEach, etc.

请注意,通常情况下,通常比在forin、forEach等等中更有效。

#8


20  

I've tested all combinations of pre-allocating/not pre-allocating, counting up/down, and for/while loops in IE 6/7/8, Firefox 3.5, Chrome, and Opera.

我已经测试了所有预分配/不预分配的组合,包括IE 6/7/8、Firefox 3.5、Chrome和Opera的循环。

The functions below was consistently the fastest or extremely close in Firefox, Chrome, and IE8, and not much slower than the fastest in Opera and IE 6. It's also the simplest and clearest in my opinion. I've found several browsers where the while loop version is slightly faster, so I'm including it too for reference.

下面的功能在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;
}

or

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

#9


15  

If you use ES6, you can use Array.from() like this:

如果使用ES6,可以使用Array.from():

Array.from({ length: 3 }, () => 0);
//[0, 0, 0]

#10


14  

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

#11


13  

using object notation

使用对象的符号

var x = [];

zero filled? like...

零了?喜欢……

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

filled with 'undefined'...

充满了‘定义’……

var x = new Array(7);

obj notation with zeros

obj符号与零

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

As a side note, if you modify Array's prototype, both

作为附加说明,如果您修改了Array的原型,两者都可以。

var x = new Array();

and

var y = [];

will have those prototype modifications

会有原型修改吗?

At any rate, I wouldn't be overly concerned with the efficiency or speed of this operation, there are plenty of other things that you will likely be doing that are far more wasteful and expensive than instanciating an array of arbitrary length containing zeros.

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

#12


12  

If you need to create many zero filled arrays of different lengths during the execution of your code, the fastest way I've found to achieve this is to create a zero array once, using one of the methods mentioned on this topic, of a length which you know will never be exceeded, and then slice that array as necessary.

如果您需要创建许多零填充不同长度的数组在执行你的代码的,最快的方法我发现实现这一目标是创建一个零的数组,使用这个话题上提到的方法之一,对一个你知道永远不会超过长度,然后切片数组作为必要的。

For example (using the function from the chosen answer above to initialize the array), create a zero filled array of length maxLength, as a variable visible to the code that needs zero arrays:

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

var zero = newFilledArray(maxLength, 0);

Now slice this array everytime you need a zero filled array of length requiredLength < maxLength:

现在,每次你需要一个长度为零的长度的数组时,将这个数组切片。

zero.slice(0, requiredLength);

I was creating zero filled arrays thousands of times during execution of my code, this speeded up the process tremendously.

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

#13


10  

The way I usually do it (and is amazing fast) is using Uint8Array. For example, creating a zero filled vector of 1M elements:

我通常使用Uint8Array(而且速度很快)。例如,创建一个包含100万个元素的零填充向量:

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

I'm a Linux user and always have worked for me, but once a friend using a Mac had some non-zero elements. I thought his machine was malfunctioning, but still here's the safest way we found to fix it:

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

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

Edited

编辑

Chrome 25.0.1364.160

Chrome 25.0.1364.160

  1. Frederik Gottlieb - 6.43
  2. 弗雷德里克Gottlieb - 6.43
  3. Sam Barnum - 4.83
  4. 萨姆巴纳姆- 4.83
  5. Eli - 3.68
  6. 伊莱- 3.68
  7. Joshua 2.91
  8. 约书亚2.91
  9. Mathew Crumley - 2.67
  10. 马修Crumley - 2.67
  11. bduran - 2.55
  12. bduran - 2.55
  13. Allen Rice - 2.11
  14. 艾伦水稻- 2.11
  15. kangax - 0.68
  16. kangax - 0.68
  17. Tj. Crowder - 0.67
  18. Tj。克劳德- 0.67
  19. zertosh - ERROR
  20. zertosh——错误

Firefox 20.0

Firefox 20.0

  1. Allen Rice - 1.85
  2. 艾伦水稻- 1.85
  3. Joshua - 1.82
  4. 约书亚- 1.82
  5. Mathew Crumley - 1.79
  6. 马修Crumley - 1.79
  7. bduran - 1.37
  8. bduran - 1.37
  9. Frederik Gottlieb - 0.67
  10. 弗雷德里克Gottlieb - 0.67
  11. Sam Barnum - 0.63
  12. 萨姆巴纳姆- 0.63
  13. Eli - 0.59
  14. 伊莱- 0.59
  15. kagax - 0.13
  16. kagax - 0.13
  17. Tj. Crowder - 0.13
  18. Tj。克劳德- 0.13
  19. zertosh - ERROR
  20. zertosh——错误

Missing the most important test (at least for me): the Node.js one. I suspect it close to Chrome benchmark.

错过了最重要的测试(至少对我来说):节点。js。我怀疑它接近Chrome的基准。

#14


8  

Using lodash or underscore

使用lodash或下划线

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

Or if you have an array existing and you want an array of the same length

或者如果你有一个数组,你想要一个相同长度的数组。

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

#15


7  

I have nothing against:

我并不反对:

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

suggested by Zertosh, but in a new ES6 array extensions allow you to do this natively with fill method. Now IE edge, Chrome and FF supports it, but check the compatibility table

由Zertosh建议,但是在新的ES6数组扩展中允许您使用填充方法进行本机操作。现在IE edge, Chrome和FF支持它,但是检查兼容性表。

new Array(3).fill(0) will give you [0, 0, 0]. You can fill the array with any value like new Array(5).fill('abc') (even objects and other arrays).

新数组(3).fill(0)将给你[0,0,0]。你可以用任何值来填充数组,比如new array (5).fill('abc')(甚至是对象和其他数组)。

On top of that you can modify previous arrays with fill:

除此之外,您还可以用fill修改前面的数组:

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

which gives you: [1, 2, 3, 9, 9, 6]

它给了你:[1,2,3,9,9,6]

#16


6  

What about new Array(51).join('0').split('')?

关于新数组(51). join(“0”).split(”)?

#17


6  

Didn't see this method in answers, so here it is:

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

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

In result you will get zero-valued array of length 200:

在结果中,你将得到长度为200的零值数组:

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

I'm not sure about the performance of this code, but it shouldn't be an issue if you use it for relatively small arrays.

我不确定这段代码的性能,但是如果您使用它来处理相对较小的数组,它就不应该是一个问题。

#18


6  

As of ECMAScript2016, there is one clear choice for large arrays.

在ECMAScript2016中,对于大型数组有一个明确的选择。

Since this answer still shows up near the top on google searches, here's an answer for 2017.

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

Here's a current jsbench with a few dozen popular methods, including many proposed up to now on this question. If you find a better method please add, fork and share.

这里有一个现有的jsbench,有几十种流行的方法,其中包括许多现在对这个问题提出的建议。如果你找到了更好的方法,请添加,fork和share。

I want to note that there is no true most efficient way to create an arbitrary length zero filled array. You can optimize for speed, or for clarity and maintainability - either can be considered the more efficient choice depending on the needs of the project.

我要注意的是,没有最有效的方法来创建任意长度为零的数组。您可以优化速度,或者为了清晰和可维护性——根据项目的需要,可以考虑更高效的选择。

When optimizing for speed, you want to: create the array using literal syntax; set the length, initialize iterating variable, and iterate through the array using a while loop. Here's an example.

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

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

Another possible implementation would be:

另一个可能的实现是:

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

But I strongly discourage using this second implantation in practice as it's less clear and doesn't allow you to maintain block scoping on your array variable.

但是我强烈反对在实践中使用第二个移植,因为它不太清楚,并且不允许您在数组变量上维护块范围。

These are significantly faster than filling with a for loop, and about 90% faster than the standard method of

这比用for循环填充要快得多,比标准方法快90%。

const arr = Array(n).fill(0);

But this fill method is still the most efficient choice for smaller arrays due to it's clarity, conciseness and maintainability. The performance difference likely won't kill you unless you're making a lot of arrays with lengths on the order of thousands or more.

但是由于它的清晰、简洁和可维护性,这个填充方法仍然是小数组的最有效的选择。性能差异很可能不会杀死您,除非您已经在数千或更多的订单上做了大量的数组。

A few other important notes. Most style guides recommend you no longer use varwithout a very special reason when using ES6 or later. Use const for variables that won't be redefined and let for variables that will. The MDN and Airbnb's Style Guide are great places to go for more information on best practices. The questions wasn't about syntax, but it's important that people new to JS know about these new standards when searching through these reams of old and new answers.

还有一些重要的笔记。大多数风格指南建议您在使用ES6或更高版本时不再使用varwithout一个非常特殊的原因。对于不能重新定义的变量,使用const,并让变量可以。MDN和Airbnb的风格指南是获得更多关于最佳实践的更多信息的好地方。这些问题与语法无关,但是当人们通过这些大量的旧的和新的答案来搜索时,对这些新标准的了解是很重要的。

#19


5  

My fastest function would be:

最快的函数是:

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

Using the native push and shift to add items to the array is much faster (about 10 times) than declaring the array scope and referencing each item to set it's value.

使用本机push和shift向数组添加项要快得多(大约10倍),而不是声明数组范围并引用每个项来设置它的值。

fyi: I consistently get faster times with the first loop, which is counting down, when running this in firebug (firefox extension).

在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

I'm interested to know what T.J. Crowder makes of that ? :-)

我想知道T.J. Crowder是怎么做的?:-)

#20


5  

I was testing out the great answer by T.J. Crowder, and came up with a recursive merge based on the concat solution that outperforms any in his tests in Chrome (i didn't test other browsers).

我正在测试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;
},

call the method with makeRec(29).

用makeRec(29)调用该方法。

#21


4  

This concat version is much faster in my tests on Chrome (2013-03-21). About 200ms for 10,000,000 elements vs 675 for straight init.

在我对Chrome的测试(2013-03-21)中,这个concat版本的速度要快得多。大约200ms, 10,000,000元素vs 675,直接init。

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: if you want to fill your array with Strings, this is a concise way to do it (not quite as fast as concat though):

好处:如果你想用字符串填充你的数组,这是一个简洁的方法(不像concat那样快):

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

#22


4  

It might be worth pointing out, that Array.prototype.fill had been added as part of the ECMAScript 6 (Harmony) proposal. I would rather go with the polyfill written below, before considering other options mentioned on the thread.

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

#23


3  

I knew I had this proto'd somewhere :)

我知道我在某处有这样一个原型:)

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

Edit: tests

编辑:测试

In response to Joshua and others methods I ran my own benchmarking, and I'm seeing completely different results to those reported.

作为对Joshua和其他方法的回应,我使用了自己的基准测试,我看到了完全不同的结果。

Here's what I tested:

以下是我测试:

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

Results:

结果:

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

So by my reckoning push is indeed slower generally but performs better with longer arrays in FF but worse in IE which just sucks in general (quel surprise).

所以根据我的计算,推的速度确实较慢,但在FF中表现得更好,但在IE中更糟糕(quel surprise)。

#24


3  

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

usage in expressions: arr[i]*1;

使用表达式:加勒比海盗[我]* 1;

EDIT: if arr supposed to be used in integer expressions, then please don't mind the char value of '0'. You just use it as follows: a = a * arr[i] (assuming a has integer value).

编辑:如果arr应该被用于整数表达式,那么请不要介意“0”的char值。您只需要使用它如下:a = a * arr[i](假设a具有整数值)。

#25


3  

Shortest for loop code

最短的for循环代码

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版本

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

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

#26


3  

ES6 solution:

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

#27


1  

The fastest way to do that is with forEach =)

最快的方法是使用forEach =)

(we keep backward compatibility for IE < 9)

(我们保持IE < 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']

#28


1  

There's always the phpjs solution, which you can find here:

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

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

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

I can't speak for the project (creating a library of javascript functions that mirrors the greater functionality of php) as a whole, but the few functions that I've personally pulled from there have worked like a champ.

我不能为这个项目说话(创建一个javascript函数库,它反映了php更强大的功能),但是我从那里获得的几个功能就像一个冠军。

#29


1  

I just use :

我只是使用:

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

#30


1  

Anonymous function:

匿名函数:

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

A bit shorter with for-loop:

更短的for循环:

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

Works with any Object, just change what's inside this.push().

与任何对象一起工作,只要改变这个。push()。

You can even save the function:

你甚至可以保存函数:

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

Call it using:

叫它使用:

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

Adding elements to an already existing array:

向已经存在的数组中添加元素:

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

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

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


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.itdaan.com/blog/2009/08/18/b9bd22e0349c953f7456adfc47fd2fe6.html



 
© 2014-2018 ITdaan.com 粤ICP备14056181号