JavaScript에서 임의의 길이 0으로 채워진 배열을 만드는 가장 효율적인 방법은 무엇입니까?
let i = 0; Array.from(Array(10), ()=>i++);
JavaScript에서 임의의 길이 0으로 채워진 배열을 만드는 가장 효율적인 방법은 무엇입니까?
let i = 0; Array.from(Array(10), ()=>i++);
답변:
ES6가 소개 Array.prototype.fill
합니다. 다음과 같이 사용할 수 있습니다 :
new Array(len).fill(0);
그것이 빠르면 확실하지 않지만 짧고 자체 설명하기 때문에 좋아합니다.
여전히 IE 에는 없지만 ( 호환성 검사 ) polyfill을 사용할 수 있습니다 .
new Array(len)
고통스럽게 느립니다. (arr = []).length = len; arr.fill(0);
가장 빠른 솔루션에 관한 어디서나 볼 ... 또는 적어도 묶여 필자
arr = Array(n)
및 (arr = []).length = n
사양에 따라 동일하게 동작합니다. 일부 구현에서는 더 빠를 수 있지만 큰 차이는 없다고 생각합니다.
(arr = []).length = 1000;
에 대해이 줄 을 사용하면 arr = new Array(1000);
... new
매우 느립니다. 이제 배열 길이가 더 작은 경우 <50 또는 약 50 정도가 new Array()
더 좋습니다.
arr.fill(0)
... 모든 것이 변합니다. 이제 new Array()
배열 크기> 100000에 도달 할 때를 제외하고 대부분의 경우 사용 이 더 빠릅니다. 그러면 속도가 다시 증가하는 것을 볼 수 있습니다. 그러나 실제로 0으로 미리 채울 필요가 없으며 빈 배열의 표준 falisy를 사용할 수 있습니다. 그렇다면 (arr = []).length = x
대부분의 경우 테스트 사례에서 미치게 빠릅니다.
new Array(5).forEach(val => console.log('hi'));
대 new Array(5).fill(undefined).forEach(val => console.log('hi'));
.
이것은 오래된 실이지만 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 (숫자) (문자열 내부의 0)을 원하면 다음을 수행 할 수 있습니다.
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
Array.apply(null, new Array(5)).map(...)
시겠습니까? 스펙이 알려주는 것처럼 단순히 (new Array (5)). map (...)하는 것은 작동하지 않습니다
new
) Array(5)
당신이 다음과 같은 객체를 만들 때 : { length: 5, __proto__: Array.prototype }
-try console.dir( Array(5) )
. 주의 사항은 어떤 속성을 가지고 있지 않음을 0
, 1
, 2
, 등하지만 당신을 때 apply
에게 있음을 Array
생성자, 그것은 말처럼 Array(undefined, undefined, undefined, undefined, undefined)
. 그리고 당신은 좀 비슷한 객체를 얻습니다 { length: 5, 0: undefined, 1: undefined...}
. map
속성에서 작동 0
, 1
등을하는 당신의 예를 들어 일을하지 않는 이유는,하지만 당신은 사용하는 경우 apply
는 않습니다.
.apply
는 실제로 원하는 this
것입니다. 이러한 목적을 위해 this
중요하지 않습니다 – 우리는 "기능"을 퍼뜨리는 매개 변수에만 관심이 .apply
있기 때문에 어떤 값이든 될 수 있습니다. 나는 null
그것이 싸기 때문에 좋아 합니다. 아마도 사용하고 싶지 {}
않거나 []
아무 이유없이 객체를 인스턴스화했기 때문입니다.
지금까지 아무도 언급하지 않은 ES6을 사용하여 수행하는 또 다른 방법은 다음과 같습니다.
> Array.from(Array(3), () => 0)
< [0, 0, 0]
지도 함수를의 두 번째 매개 변수로 전달하여 작동합니다 Array.from
.
위의 예에서 첫 번째 매개 변수는 값으로 채워진 3 개의 위치로 구성된 배열을 할당 한 undefined
다음 람다 함수가 이들 각각을 값에 매핑합니다 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()
원하는 값으로 ping합니다. 단계별로 분류 :
> "?".repeat(10)
< "??????????"
> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
repeat
트릭은 확실히 생산에 원하지 않는, Array.from()
:-) 완벽하게 괜찮
가장 빠른 솔루션
let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
가장 짧은 (핸디) 솔루션
Array(n).fill(0)
오늘 2020.06.09 Chrome 83.0, Firefox 77.0 및 Safari 13.1 브라우저에서 macOS High Sierra 10.13.6에서 테스트를 수행합니다. 두 가지 테스트 사례에 대해 선택한 솔루션을 테스트합니다.
new Array(n)+for
(N) 기반 솔루션은 소형 어레이 및 대형 어레이에 가장 빠른 솔루션이며 (Chrome 제외하지만 여전히 빠름) 빠른 크로스 브라우저 솔루션으로 권장됩니다.new Float32Array(n)
(I) 기반 솔루션 은 비 전형적인 배열을 반환 push(..)
하므로 (예를 들어 호출 할 수 없음 ) 결과를 다른 솔루션과 비교할 수는 없지만이 솔루션은 모든 브라우저에서 큰 배열의 다른 솔루션보다 약 10-20 배 빠릅니다.for
(L, M, N, O) 기반 솔루션 은 소형 어레이에 빠릅니다.fill
(B, C) 기반 솔루션 은 Chrome 및 Safari에서 빠르지 만 큰 배열의 경우 Firefox에서 가장 느립니다. 그들은 작은 배열에 대해 중간 속도입니다Array.apply
(P) 기반 솔루션 은 큰 배열에서 오류를 발생시킵니다.
아래 코드는 측정에 사용되는 솔루션을 나타냅니다.
Chrome의 결과 예
let a=[]; for(i=n;i--;) a.push(0);
그러나 4 배 느립니다 fill(0)
.
이미 언급 한 ES 6 채우기 방법은이를 잘 처리합니다. 대부분의 최신 데스크탑 브라우저는 이미 현재 필요한 배열 프로토 타입 방법 (Chromium, FF, Edge 및 Safari)을 지원합니다 [ 1 ]. MDN에 대한 세부 정보를 찾을 수 있습니다 . 간단한 사용법 예는
a = new Array(10).fill(0);
현재 브라우저 지원이 제공되므로 사용자가 최신 데스크탑 브라우저를 사용하고 있는지 확신 할 수없는 경우이를 사용하는 것이 좋습니다.
a = Array(10).fill(null).map(() => { return []; });
a = Array(10).fill(0).map( _ => [] );
참고 : 2013 년 8 월 추가, 2015 년 2 월 업데이트 : 2009 년 아래 답변은 JavaScript의 일반 Array
유형과 관련이 있습니다. ES2015에 정의되어 있고 현재 많은 브라우저에서 사용 가능한 최신 유형의 배열 과 관련이 없습니다 Int32Array
. 또한 ES2015은 추가 점에 유의 fill
모두 방법을 배열 하고 입력 배열 을 채우기 위해 가장 효율적인 방법이 될 것입니다 ...
또한 배열을 만드는 방법에 따라 구현에 큰 차이가 생길 수 있습니다. 특히 Chrome의 V8 엔진은 가능한 경우 고효율의 연속 메모리 배열을 사용하여 필요할 때만 객체 기반 배열로 이동하려고 시도합니다.
대부분의 언어에서는 다음과 같이 사전 할당 된 후 0으로 채워집니다.
function newFilledArray(len, val) {
var rv = new Array(len);
while (--len >= 0) {
rv[len] = val;
}
return rv;
}
그러나 JavaScript 배열 은 실제로 배열 이 아니며 다른 모든 JavaScript 객체와 마찬가지로 키 / 값 맵이므로 "할당"할 필요가 없습니다 (길이를 설정해도 많은 슬롯을 채울 수는 없습니다). 구현이 키 처리를 최적화했을 때 키를 역순으로 추가하여 0으로 카운트 다운하는 이점 (루프에서 비교를 빠르게하는 것)이 중요하지 않다고 믿을만한 이유가 있습니까? 이론적으로 배열과 관련하여 일반적으로 순서대로 수행합니다.
실제로 Matthew Crumley는 Firefox에서 카운트 다운이 카운트 업보다 카운트 다운이 현저히 느리다는 것을 지적했습니다. 결과는 확인할 수 있습니다. 배열의 일부입니다 (0에서 루핑하는 것이 var의 한계까지 루핑하는 것보다 여전히 빠릅니다). Firefox에서 요소를 역순으로 배열에 추가하는 것은 분명히 느린 작업입니다. 실제로 결과는 JavaScript 구현에 따라 상당히 다양합니다 (놀라운 것은 아닙니다). 다음은 브라우저 구현을위한 빠르고 더러운 테스트 페이지 (아래)입니다 (매우 더럽고 테스트 중에 생성되지 않으므로 최소한의 피드백 만 제공하며 스크립트 시간 제한을 무시 함). 테스트 사이에 새로 고침을 권장합니다. 그렇지 않으면 반복 테스트에서 FF (적어도)가 느려집니다.
Array # concat을 사용하는 상당히 복잡한 버전은 1,000에서 2,000 개의 요소 배열보다 FF에서 바로 초기화하는 것보다 빠릅니다. 그러나 Chrome의 V8 엔진에서는 straight init가 매번 승리합니다.
테스트 페이지는 다음과 같습니다 ( 라이브 사본 ).
<!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>
기본적으로 Uint8Array
, Uint16Array
그리고 Uint32Array
클래스를 사용하면 복잡한 충전 기술을 필요가 없습니다, 단지 수행의 값으로 0을 유지 :
var ary = new Uint8Array(10);
배열의 모든 요소는 ary
기본적으로 0입니다.
Array.isArray(ary)
is) false
. 길이는 읽기 전용이므로 다음과 같이 새 항목을 푸시 할 수 없습니다ary.push
0
기본 값으로 유지 합니다.
Array.from(new Uint8Array(10))
은 일반 배열을 제공합니다.
Array(n).fill(0)
실제로 필요한 것이 JS 배열 인 경우 Chrome 보다 약 5 배 느리다는 것을 보여줍니다 . TypedArray를 사용할 수 있다면 .fill(0)
, 특히 기본 초기화 값인을 사용할 수있는 경우 보다 훨씬 빠릅니다 0
. C ++과 같은 채우기 값과 길이를 취하는 생성자가없는 것 같습니다 std::vector
. 0이 아닌 값의 경우 0으로 된 TypedArray를 구성한 다음 채워야합니다. : /
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]
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-in
, forEach
등
i
지역 변수의 관계없는? length
값으로 전달되므로 직접 줄일 수 있습니다.
arr[i] = value
. 처음부터 끝까지 반복하고 사용하는 것이 훨씬 빠릅니다 arr.push(value)
. 나는 당신의 방법을 선호하기 때문에 성가시다.
객체 표기법 사용
var x = [];
제로 가득? 처럼...
var x = [0,0,0,0,0,0];
'정의되지 않음'으로 채워진 ...
var x = new Array(7);
0으로 된 obj 표기법
var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;
참고로, Array의 프로토 타입을 수정하면
var x = new Array();
과
var y = [];
프로토 타입 수정이있을 것입니다
어쨌든, 나는이 작업의 효율성이나 속도에 지나치게 신경 쓰지 않을 것입니다 .0을 포함하는 임의의 길이의 배열을 설정하는 것보다 훨씬 더 낭비적이고 비쌀만한 일이 많이 있습니다.
null
이 배열 에는 s 가 없습니다 –var x = new Array(7);
new Array(7)
않는 하지 배열 "미정 충전"을 생성한다. 길이가 7 인 빈 배열을 만듭니다 .
(new Array(10)).fill(0)
.
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;
}
var array = []
선언문을 실제로 for 루프의 첫 번째 부분에 쉼표로 구분하여 던질 수도 있습니다 .
length
이미 주어진 값으로 설정하여 끊임없이 변경되지 않도록하십시오. 내 컴퓨터에서 40ms에서 8까지 백만 길이의 0을 가져 왔습니다.
for (i = 0, array = []; i < length; ++i) array[i] = val;
.. 더 적은 블록? ... 어쨌든 ... array.length
새로운 배열의 길이를 길이로 설정하면 FF에서 10 % -15 %의 속도가 다시 증가하는 것 같습니다 ... Chrome에서는 속도가 두 배가되는 것 같습니다-> var i, array = []; array.length = length; while(i < length) array[i++] = val;
( for
루프 로 남겨두면 여전히 더 빠르지 만 ... init가 더 이상 필요하지 while
코드 실행 중에 길이가 다른 0으로 채워진 많은 배열을 만들어야하는 경우이를 달성하는 가장 빠른 방법은 이 주제에서 언급 한 방법 중 하나를 사용하여 길이 가 0 인 배열을 한 번 만드는 것입니다 당신은 알고 초과하지 않을 것입니다 그리고 필요에 따라 그 배열을 슬라이스.
예를 들어 (위의 선택된 답변의 함수를 사용하여 배열을 초기화하는 경우) 길이가 0 인 배열의 maxLength 배열을 0의 배열이 필요한 코드에 표시되는 변수로 만듭니다 .
var zero = newFilledArray(maxLength, 0);
이제 길이가 0 인 채워진 배열이 필요할 때마다이 배열을 슬라이스하십시오. requiredLength < maxLength :
zero.slice(0, requiredLength);
코드를 실행하는 동안 수천 번 채워진 배열을 수천 번 만들었으므로 프로세스 속도가 엄청나게 빨라졌습니다.
나는 반대 할 것이 없다 :
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);
Zertosh에서 제안했지만 새로운 ES6 배열 확장에서는 기본적으로 fill
메소드를 사용 하여이 작업을 수행 할 수 있습니다 . 이제 IE edge, Chrome 및 FF가 지원하지만 호환성 표를 확인하십시오.
new Array(3).fill(0)
당신에게 줄 것이다 [0, 0, 0]
. 배열은 new Array(5).fill('abc')
객체 및 기타 배열과 같은 값으로 채울 수 있습니다 .
그 외에도 채우기로 이전 배열을 수정할 수 있습니다.
arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5) # what to fill, start, end
그것은 당신에게 제공합니다 : [1, 2, 3, 9, 9, 6]
내가 일반적으로하는 방법 (그리고 놀랍습니다)은을 사용하고 Uint8Array
있습니다. 예를 들어 1M 요소로 채워진 0으로 채워진 벡터 만들기 :
var zeroFilled = [].slice.apply(new Uint8Array(1000000))
나는 Linux 사용자이고 항상 나를 위해 일했지만 Mac을 사용하는 친구에게는 0이 아닌 요소가있었습니다. 나는 그의 기계가 오작동하고 있다고 생각했지만 여전히 여기에서 우리가 발견 한 가장 안전한 방법이 있습니다.
var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000))
편집
크롬 25.0.1364.160
파이어 폭스 20.0
Node.js와 같은 가장 중요한 테스트가 없습니다. Chrome 벤치 마크와 가깝습니다.
_.range(0, length, 0)
한다고 믿습니다. Lodash는 최종 가치를 배제합니다
ECMAScript2016 기준으로 대규모 어레이에 대한 명확한 선택이 있습니다.
이 답변은 여전히 Google 검색에서 맨 위에 표시되므로 2017에 대한 답변입니다.
다음 은이 질문에 지금까지 제안 된 많은 것을 포함하여 수십 가지 인기있는 메소드 가있는 현재 jsbench 입니다. 더 나은 방법을 찾으면 추가, 포크 및 공유하십시오.
임의의 길이의 0으로 채워진 배열을 만드는 가장 효율적인 방법은 없습니다. 속도 또는 명확성 및 유지 관리 성을 위해 최적화 할 수 있습니다. 프로젝트의 요구에 따라보다 효율적인 선택으로 간주 될 수 있습니다.
속도를 최적화 할 때 다음을 수행하려고합니다. 리터럴 구문을 사용하여 배열을 작성하십시오. 길이를 설정하고 반복 변수를 초기화하고 while 루프를 사용하여 배열을 반복하십시오. 다음은 예입니다.
const arr = [];
arr.length = 120000;
let i = 0;
while (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);
그러나이 채우기 방법은 명확성, 간결성 및 유지 관리 성으로 인해 더 작은 어레이에 가장 효율적인 선택입니다. 수천 가지 이상의 길이를 가진 배열을 많이 만들지 않으면 성능 차이로 인해 죽지 않을 것입니다.
몇 가지 중요한 참고 사항. 대부분의 스타일 가이드는 var
ES6 이상을 사용할 때 특별한 이유 없이는 더 이상 사용 하지 않는 것이 좋습니다 . const
재정의되지 않는 변수와 변수에 사용하십시오 let
. MDN 및 에어 비앤비의 스타일 가이드 모범 사례에 대한 자세한 내용은 갈 좋은 장소입니다. 질문은 구문에 관한 것이 아니라 JS를 처음 접하는 사람들이 구식의 새로운 답변을 검색 할 때 이러한 새로운 표준에 대해 아는 것이 중요합니다.
완전히 새로운 배열을 만들려면
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)]);
답변 에서이 방법을 보지 못 했으므로 여기에 있습니다.
"0".repeat( 200 ).split("").map( parseFloat )
결과적으로 길이가 200 인 값이 0 인 배열을 얻게됩니다.
[ 0, 0, 0, 0, ... 0 ]
이 코드의 성능에 대해 잘 모르겠지만 비교적 작은 배열에 사용하면 문제가되지 않습니다.
const arr = Array.from({ length: 10 }).fill(0)
이 concat
버전은 Chrome 테스트 (2013-03-21)에서 훨씬 빠릅니다. 10,000,000 개의 요소에 대해 약 200ms vs. 직선 초기화에 대한 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('');
}
TJ Crowder가 큰 대답을 테스트하고 Chrome에서 테스트보다 성능이 우수한 concat 솔루션을 기반으로 재귀 병합을 수행했습니다 (다른 브라우저는 테스트하지 않았습니다).
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)
.
그것은 지적 가치, 수도 Array.prototype.fill
의 일환으로 추가되었다 ECMAScript를 6 (하모니) 제안 . 스레드에 언급 된 다른 옵션을 고려하기 전에 아래에 작성된 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;
};
}
가장 짧은 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;
안전한 var 버전
var a=[],i=0;for(;i<100;)a[i++]=0;
edit:
for(var i=100,a=[];i--;)a[i]=0;
n
경우이 길이는 더 짧습니다.for(var a=[];n--;a[n]=0);
let filled = [];
filled.length = 10;
filled.fill(0);
console.log(filled);
가장 빠른 기능은 다음과 같습니다.
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
기본 푸시 앤 시프트를 사용하여 배열에 항목을 추가하면 배열 범위를 선언하고 각 항목을 참조하여 값을 설정하는 것보다 훨씬 빠릅니다 (약 10 배).
fyi : firebug (firefox extension)에서 이것을 실행할 때 카운트 다운되는 첫 번째 루프로 일관되게 더 빠른 시간을 얻습니다.
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
TJ Crowder가 무엇을하는지 알고 싶습니다. :-)
while (len--)
54ms 정도까지 60ms 대해에서 내 처리 시간을했다 ..
나는이 프로토가 어딘가에 있음을 알았습니다 :)
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).
b = []...
)은 첫 번째 방법 보다 10-15 % 빠르지 만 Joshua의 답변보다 10 배 이상 느립니다.
else {this.length=n;}
애프터 this.length
-check. 필요한 경우 init
다른 길이로 재 다이얼 할 때 기존 어레이 를 줄 n
입니다.
익명의 기능 :
(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']