Was ist der effizienteste Weg, um eine beliebige Länge Null gefüllt Array in JavaScript zu erstellen?
Antworten
Zu viele Anzeigen?ES6 führt ein Array.prototype.fill
. Sie kann wie folgt verwendet werden:
new Array(len).fill(0);
Ich weiß nicht, ob es schnell ist, aber ich mag es, weil es kurz und selbsterklärend ist.
Es ist immer noch nicht im IE ( Kompatibilität prüfen ), aber es gibt eine Polyfill verfügbar .
Obwohl dies ein altes Thema ist, wollte ich meine 2 Cents dazu beitragen. Ich bin mir nicht sicher, wie langsam/schnell das ist, aber es ist ein schneller Einzeiler. Hier ist, was ich tue:
Wenn ich eine Zahl vorausfüllen möchte:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
Wenn ich eine Zeichenkette vorfüllen möchte:
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
Andere Antworten haben vorgeschlagen:
new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
aber wenn Sie 0 (die Zahl) und nicht "0" (Null innerhalb einer Zeichenkette) wollen, können Sie das tun:
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]
Kurzum
Die schnellste Lösung:
let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
Kürzeste (praktische) Lösung (3x langsamer für kleine Arrays, etwas langsamer für große (am langsamsten auf Firefox))
Array(n).fill(0)
Einzelheiten
Heute 2020.06.09 führe ich Tests auf macOS High Sierra 10.13.6 mit den Browsern Chrome 83.0, Firefox 77.0 und Safari 13.1 durch. Ich teste ausgewählte Lösungen für zwei Testfälle
- kleinen Array - mit 10 Elementen - können Sie einen Test durchführen HIER
- großen Arrays - mit 1M Elementen - können Sie Tests durchführen HIER
Schlussfolgerungen
- Lösung basierend auf
new Array(n)+for
(N) ist die schnellste Lösung für kleine und große Arrays (außer Chrome, aber auch dort sehr schnell) und wird als schnelle, browserübergreifende Lösung empfohlen - Lösung basierend auf
new Float32Array(n)
(I) gibt ein untypisches Array zurück (z.B. können Sie nichtpush(..)
daher kann ich die Ergebnisse nicht mit anderen Lösungen vergleichen - allerdings ist diese Lösung bei großen Arrays auf allen Browsern etwa 10-20x schneller als andere Lösungen - Lösungen basierend auf
for
(L,M,N,O) sind schnell für kleine Arrays - Lösungen basierend auf
fill
(B,C) sind schnell auf Chrome und Safari, aber überraschenderweise am langsamsten auf Firefox für große Arrays. Sie sind mittelschnell für kleine Arrays -
Lösung basierend auf
Array.apply
(P) wirft Fehler bei großen Arraysfunction P(n) { return Array.apply(null, Array(n)).map(Number.prototype.valueOf,0); } try { P(1000000); } catch(e) { console.error(e.message); }
Code und Beispiel
Der nachstehende Code enthält die bei den Messungen verwendeten Lösungen
function A(n) {
return [...new Array(n)].fill(0);
}
function B(n) {
return new Array(n).fill(0);
}
function C(n) {
return Array(n).fill(0);
}
function D(n) {
return Array.from({length: n}, () => 0);
}
function E(n) {
return [...new Array(n)].map(x => 0);
}
// arrays with type
function F(n) {
return Array.from(new Int32Array(n));
}
function G(n) {
return Array.from(new Float32Array(n));
}
function H(n) {
return Array.from(new Float64Array(n)); // needs 2x more memory than float32
}
function I(n) {
return new Float32Array(n); // this is not typical array
}
function J(n) {
return [].slice.apply(new Float32Array(n));
}
// Based on for
function K(n) {
let a = [];
a.length = n;
let i = 0;
while (i < n) {
a[i] = 0;
i++;
}
return a;
}
function L(n) {
let a=[]; for(let i=0; i<n; i++) a[i]=0;
return a;
}
function M(n) {
let a=[]; for(let i=0; i<n; i++) a.push(0);
return a;
}
function N(n) {
let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
return a;
}
function O(n) {
let a = new Array(n); for (let i=n; i--;) a[i] = 0;
return a;
}
// other
function P(n) {
return Array.apply(null, Array(n)).map(Number.prototype.valueOf,0);
}
function Q(n) {
return "0".repeat( n ).split("").map( parseFloat );
}
function R(n) {
return new Array(n+1).join('0').split('').map(parseFloat)
}
// ---------
// TEST
// ---------
[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R].forEach(f => {
let a = f(10);
console.log(`${f.name} length=${a.length}, arr[0]=${a[0]}, arr[9]=${a[9]}`)
});
This snippets only present used codes
Beispielergebnisse für Chrome:
Elegante Art, ein Array mit vorberechneten Werten zu füllen
Hier ist eine weitere Möglichkeit, ES6 zu verwenden, die bisher noch niemand erwähnt hat:
> Array.from(Array(3), () => 0)
< [0, 0, 0]
Sie funktioniert durch Übergabe einer Map-Funktion als zweiten Parameter von Array.from
.
Im obigen Beispiel weist der erste Parameter ein Array mit 3 Positionen zu, das mit dem Wert undefined
und dann ordnet die Lambda-Funktion jedes dieser Elemente dem Wert 0
.
Obwohl Array(len).fill(0)
kürzer ist, funktioniert es nicht, wenn Sie das Array füllen müssen, indem Sie zuerst eine Berechnung durchführen (Ich weiß, dass in der Frage nicht danach gefragt wurde, aber viele Leute landen hier, wenn sie danach suchen) .
Wenn Sie zum Beispiel ein Array mit 10 Zufallszahlen benötigen:
> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]
Sie ist prägnanter (und eleganter) als das Äquivalent:
const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
numbers[i] = Math.round(10 * Math.random());
}
Diese Methode kann auch verwendet werden, um Zahlenfolgen zu generieren, indem man den im Callback bereitgestellten Indexparameter nutzt:
> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Bonusantwort: Füllen eines Arrays mit String repeat()
Da diese Antwort viel Aufmerksamkeit erregt, wollte ich auch diesen coolen Trick zeigen. Obwohl nicht so nützlich wie meine Hauptantwort, wird der noch nicht sehr bekannte, aber sehr nützliche String vorgestellt repeat()
Methode. Hier ist der Trick:
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Cool, nicht wahr? repeat()
ist eine sehr nützliche Methode, um eine Zeichenkette zu erstellen, die eine bestimmte Anzahl von Wiederholungen der ursprünglichen Zeichenkette darstellt. Danach, split()
erstellt ein Array für uns, das dann map()
zu den von uns gewünschten Werten zu bringen. Die Aufschlüsselung in Schritten:
> "?".repeat(10)
< "??????????"
> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Mit der bereits erwähnten ES 6-Füllmethode lässt sich dies gut bewerkstelligen. Die meisten modernen Desktop-Browser unterstützen die erforderlichen Array-Prototyp-Methoden bereits heute (Chromium, FF, Edge und Safari) [ 1 ]. Sie können Einzelheiten nachlesen unter MDN . Ein einfaches Anwendungsbeispiel ist
a = new Array(10).fill(0);
In Anbetracht der aktuellen Browserunterstützung sollten Sie damit vorsichtig sein, es sei denn, Sie sind sicher, dass Ihre Zielgruppe moderne Desktop-Browser verwendet.
- See previous answers
- Weitere Antworten anzeigen
7 Stimmen
Dazu einige konkrete Daten: jsperf.com/zeroarrayjs
9 Stimmen
ES6-Füllung ermöglicht dies von Haus aus.
1 Stimmen
Arr = new Array(length+1).joint(character).split('');
5 Stimmen
UPDATE 2016 : Ein weiterer benutzerdefinierter Benchmark hier: jsfiddle.net/basickarl/md5z0Lqq
4 Stimmen
let i = 0; Array.from(Array(10), ()=>i++);
1 Stimmen
Die Verwendung von typisierten Arrays könnte eine gute Option sein, wenn man zum Beispiel mit sehr großen Nachschlagetabellen arbeitet. Vergleich der Geschwindigkeit der typisierten Array-Initialisierung: jsperf.com/new-int32array-vs-array-fill
1 Stimmen
Zu Ihrer Information, Aquí ist ein Benchmark zwischen
.fill()
und for-Schleife.1 Stimmen
Was meinen Sie mit "am effizientesten"? Die wenigsten CPU-Zyklen? Geringste Speichernutzung? Den kompaktesten Quellcode?
0 Stimmen
Ich weiß, dass dies nicht der Zweck der Frage ist, aber ich habe eine Idee, die aus dem Rahmen fällt. Und warum? Mein CSci-Professor stellte fest, dass es nichts Magisches daran gibt, Daten mit Null zu "bereinigen". Der effizienteste Weg ist also NO es überhaupt tun! Tun Sie es nur, wenn die Daten immer Null sein müssen - was normalerweise NICHT der Fall ist.
0 Stimmen
Diese Frage könnte die schlechtesten Antworten auf Stack Overflow haben. Die Frage ist, welche Methode die effizienteste ist. 85% der Antworten versuchen nicht einmal, die Frage zu beantworten, sondern führen nur eine Methode auf, die nicht der Frage entspricht. Selbst die wenigen, die versuchen, Benchmarks aufzulisten, scheitern alle oder haben schlechte/falsche Antworten.
0 Stimmen
Antwort ab Juni 2020 siehe jsperf.com/fill-to-const-value/1
0 Stimmen
Let arr = new Array(10).fill(0)