Was ist der effizienteste Weg, um ein Array mit beliebiger Länge und Null in JavaScript zu erstellen?
javascript
arrays
dil
quelle
quelle
let i = 0; Array.from(Array(10), ()=>i++);
Antworten:
ES6 stellt vor
Array.prototype.fill
. Es kann folgendermaßen verwendet werden:Ich bin mir nicht sicher, ob es schnell ist, aber ich mag es, weil es kurz und selbstbeschreibend ist.
Es ist immer noch nicht im IE ( Kompatibilität prüfen ), aber es ist eine Polyfüllung verfügbar .
quelle
new Array(len)
ist schmerzhaft langsam.(arr = []).length = len; arr.fill(0);
ist ungefähr die schnellste Lösung, die ich jemals gesehen habe ... oder zumindest gebundenarr = Array(n)
und(arr = []).length = n
verhalten sich entsprechend der Spezifikation identisch. In einigen Implementierungen könnte man schneller sein, aber ich glaube nicht, dass es einen großen Unterschied gibt.(arr = []).length = 1000;
gegenarr = new Array(1000);
Geschwindigkeitstest in Chrome und FF ... dasnew
ist furchtbar langsam. Nun, für Array-Längen kleiner ... sagen wir <50 oder so ungefähr ... dannnew Array()
scheint es besser zu funktionieren. Aber ..arr.fill(0)
... ändert sich alles irgendwie. Jetzt ist die Verwendungnew Array()
in den meisten Fällen schneller, außer wenn Sie Arraygrößen> 100000 erreichen ... Dann können Sie beginnen, die Geschwindigkeitssteigerung wieder zu sehen. Aber wenn Sie es nicht mit Nullen vorfüllen müssen und Standard-Falisy von leeren Arrays verwenden können. Dann(arr = []).length = x
ist in meinen Testfällen die meiste Zeit verrückt schnell.new Array(5).forEach(val => console.log('hi'));
vsnew Array(5).fill(undefined).forEach(val => console.log('hi'));
.Obwohl dies ein alter Thread ist, wollte ich meine 2 Cent hinzufügen. Ich bin mir nicht sicher, wie langsam / schnell das ist, aber es ist ein schneller Einzeiler. Folgendes mache ich:
Wenn ich eine Nummer vorab ausfüllen möchte:
Wenn ich mit einer Zeichenfolge vorfüllen möchte:
Andere Antworten haben vorgeschlagen:
Wenn Sie jedoch 0 (die Zahl) und nicht "0" (Null innerhalb einer Zeichenfolge) möchten, können Sie Folgendes tun:
quelle
Array.apply(null, new Array(5)).map(...)
? Weil einfach zu tun (neues Array (5)). Map (...) nicht funktioniert, wie die Spezifikation sagtnew
) Wenn Sie dies tunArray(5)
, erstellen Sie ein Objekt, das irgendwie so aussieht:{ length: 5, __proto__: Array.prototype }
- versuchen Sie esconsole.dir( Array(5) )
. Beachten Sie, dass es keine Eigenschaften hat0
,1
,2
etc. Aber wenn man ,apply
dass zu demArray
Konstruktor, es ist wie wenn man sagtArray(undefined, undefined, undefined, undefined, undefined)
. Und du bekommst ein Objekt, das irgendwie aussieht{ length: 5, 0: undefined, 1: undefined...}
.map
arbeitet auf die Eigenschaften0
,1
etc. weshalb Ihr Beispiel nicht funktioniert, aber wenn Sieapply
es tut..apply
ist eigentlich das, was Sie wollenthis
. Für diese Zwecke spielt dasthis
keine Rolle - wir kümmern uns nur wirklich um die Parameter-Spreizfunktion von.apply
- also kann es ein beliebiger Wert sein. Ich mag es,null
weil es billig ist, Sie es wahrscheinlich nicht verwenden möchten{}
oder[]
weil Sie ein Objekt ohne Grund instanziieren würden.Elegante Möglichkeit, ein Array mit vorberechneten Werten zu füllen
Hier ist eine andere Möglichkeit, ES6 zu verwenden, die bisher noch niemand erwähnt hat:
Es funktioniert durch Übergeben einer Kartenfunktion als zweiten Parameter von
Array.from
.Im obigen Beispiel weist der erste Parameter ein Array von 3 Positionen zu, die mit dem Wert gefüllt sind,
undefined
und dann ordnet die Lambda-Funktion jede dieser Positionen dem Wert zu0
.Obwohl
Array(len).fill(0)
es kürzer ist, funktioniert es nicht, wenn Sie das Array zuerst mit Berechnungen füllen müssen (ich weiß, dass die Frage nicht danach gefragt hat, aber viele Leute suchen hier danach). .Wenn Sie beispielsweise ein Array mit 10 Zufallszahlen benötigen:
Es ist prägnanter (und eleganter) als das Äquivalent:
Diese Methode kann auch verwendet werden, um Zahlenfolgen zu generieren, indem der im Rückruf angegebene Indexparameter genutzt wird:
Bonusantwort: Füllen Sie ein Array mit String
repeat()
Da diese Antwort viel Aufmerksamkeit erhält, 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 eingeführt. Hier ist der Trick:Cool was?
repeat()
ist eine sehr nützliche Methode, um eine Zeichenfolge zu erstellen, bei der die ursprüngliche Zeichenfolge eine bestimmte Anzahl von Malen wiederholt wird. Danachsplit()
erstellt er ein Array für uns, das dannmap()
auf die gewünschten Werte eingestellt wird. Aufteilung in Schritte:quelle
repeat
Trick in der Produktion definitiv nicht erwünscht ist,Array.from()
ist er vollkommen in Ordnung :-)Zusamenfassend
Schnellste Lösung
let a = new Array(n); for (let i=0; i<n; ++i) a[i] = 0;
Kürzeste (handliche) Lösung (3x langsamer für kleine Arrays, etwas langsamer für große (am langsamsten bei Firefox))
Array(n).fill(0)
Einzelheiten
Heute 2020.06.09 führe ich Tests unter macOS High Sierra 10.13.6 in den Browsern Chrome 83.0, Firefox 77.0 und Safari 13.1 durch. Ich teste ausgewählte Lösungen für zwei Testfälle
Schlussfolgerungen
new Array(n)+for
(N) ist die schnellste Lösung für kleine und große Arrays (außer Chrome, aber immer noch sehr schnell) und wird als schnelle browserübergreifende Lösung empfohlennew Float32Array(n)
(I) basierende Lösung gibt ein nicht typisches Array zurück (z. B. können Sie nicht aufrufenpush(..)
), sodass ich die Ergebnisse nicht mit anderen Lösungen vergleiche. Diese Lösung ist jedoch etwa 10 bis 20 Mal schneller als andere Lösungen für große Arrays in allen Browsernfor
(L, M, N, O) basieren, sind für kleine Arrays schnellfill
(B, C) , sind in Chrome und Safari schnell, in Firefox für große Arrays jedoch überraschend langsam. Sie sind mittelschnell für kleine ArraysArray.apply
(P) basierende Lösung löst einen Fehler für große Arrays ausCode-Snippet anzeigen
Code und Beispiel
Der folgende Code enthält Lösungen für Messungen
Code-Snippet anzeigen
Beispielergebnisse für Chrome
quelle
let a=[]; for(i=n;i--;) a.push(0);
- aber es ist 4x langsamer alsfill(0)
- also werde ich das Bild in diesem Fall nicht einmal aktualisieren.Die bereits erwähnte ES 6-Füllmethode sorgt dafür. Die meisten modernen Desktop-Browser unterstützen bereits heute die erforderlichen Array-Prototyp-Methoden (Chromium, FF, Edge und Safari) [ 1 ]. Sie können Details zu MDN nachschlagen . Ein einfaches Anwendungsbeispiel ist
Angesichts der aktuellen Browserunterstützung sollten Sie vorsichtig sein, es sei denn, Sie sind sicher, dass Ihre Zielgruppe moderne Desktop-Browser verwendet.
quelle
a = Array(10).fill(null).map(() => { return []; });
a = Array(10).fill(0).map( _ => [] );
Hinweis hinzugefügt August 2013, aktualisiert Februar 2015: Die folgende Antwort aus dem Jahr 2009 bezieht sich auf den generischen
Array
Typ von JavaScript . Es bezieht sich nicht auf die neueren typisierten Arrays, die in ES2015 definiert sind [und jetzt in vielen Browsern verfügbar sind], wieInt32Array
und so. Beachten Sie auch, dass ES2015fill
sowohl Arrays als auch typisierten Arrays eine Methode hinzufügt , die wahrscheinlich die effizienteste Methode ist, um sie zu füllen ...Außerdem kann es bei einigen Implementierungen einen großen Unterschied machen, wie Sie das Array erstellen. Insbesondere die V8-Engine von Chrome versucht, ein hocheffizientes Array mit zusammenhängendem Speicher zu verwenden, wenn sie dies für möglich hält, und wechselt nur bei Bedarf zum objektbasierten Array.
Bei den meisten Sprachen wird es vorab zugewiesen und dann wie folgt mit Null gefüllt:
Aber , JavaScript - Arrays sind nicht wirklich Arrays , sie sind Schlüssel / Wert - Karten wie alle anderen JavaScript - Objekte, so gibt es keine „vorbelegt“ zu tun (Einstellung der Länge zuteilen nicht , dass viele Slots zu füllen), noch Gibt es einen Grund zu der Annahme, dass der Vorteil des Herunterzählens auf Null (der nur dazu dient, den Vergleich in der Schleife schnell zu machen) nicht durch das Hinzufügen der Schlüssel in umgekehrter Reihenfolge aufgewogen wird, wenn die Implementierung möglicherweise die Handhabung der Schlüssel optimiert hat Bezogen auf Arrays in der Theorie werden Sie sie im Allgemeinen in der richtigen Reihenfolge ausführen.
Tatsächlich wies Matthew Crumley darauf hin, dass das Herunterzählen in Firefox deutlich langsamer ist als das Hochzählen, ein Ergebnis, das ich bestätigen kann - es ist der Array-Teil davon (das Schleifen auf Null ist immer noch schneller als das Schleifen bis zu einem Grenzwert in einer Var). Anscheinend ist das Hinzufügen der Elemente zum Array in umgekehrter Reihenfolge eine langsame Operation in Firefox. Tatsächlich variieren die Ergebnisse je nach JavaScript-Implementierung erheblich (was nicht allzu überraschend ist). Hier ist eine schnelle und schmutzige Testseite (unten) für Browser-Implementierungen (sehr schmutzig, gibt während der Tests nicht nach, bietet daher nur minimales Feedback und läuft unter Einhaltung der Skript-Zeitlimits). Ich empfehle, zwischen den Tests zu aktualisieren. FF verlangsamt sich (zumindest) bei wiederholten Tests, wenn Sie dies nicht tun.
Die ziemlich komplizierte Version, die Array # concat verwendet, ist schneller als ein Straight Init auf FF, und zwar zwischen 1.000 und 2.000 Elementarrays. Bei der V8-Engine von Chrome gewinnt Straight Init jedoch jedes Mal ...
Hier ist die Testseite ( Live-Kopie ):
quelle
In der Standardeinstellung
Uint8Array
,Uint16Array
undUint32Array
Klassen halten Nullen als Werte, so dass Sie keine komplexen Abfülltechniken benötigen, gerade tun:Alle Elemente des Arrays
ary
sind standardmäßig Nullen.quelle
Array.isArray(ary)
istfalse
. Die Länge ist auch schreibgeschützt, so dass Sie keine neuen Elemente wie beiary.push
0
ihren Standardwert bei.Array.from(new Uint8Array(10))
stellt ein normales Array bereit.Array(n).fill(0)
in Chrome, wenn Sie wirklich ein JS-Array benötigen. Wenn Sie ein TypedArray verwenden können, ist dies sogar viel schneller als.fill(0)
, insbesondere wenn Sie den Standardinitialisiererwert von verwenden können0
. Es scheint keinen Konstruktor zu geben, der einen Füllwert und eine Länge annimmt, wie es C ++ getanstd::vector
hat. Es scheint, dass Sie für jeden Wert ungleich Null ein typisiertes Array mit Null erstellen und es dann füllen müssen. : /Wenn Sie ES6 verwenden, können Sie Array.from () wie folgt verwenden :
Hat das gleiche Ergebnis wie
weil
quelle
Beachten Sie, dass
while
in der Regel effizienter als istfor-in
,forEach
usw.quelle
i
lokale Variable nicht irrelevant?length
wird als Wert übergeben, sodass Sie ihn direkt dekrementieren können sollten.arr[i] = value
. B. ). Es ist viel schneller, von Anfang bis Ende durchzugehen und zu verwendenarr.push(value)
. Es ist ärgerlich, weil ich Ihre Methode bevorzuge.mit Objektnotation
Null gefüllt? mögen...
gefüllt mit 'undefiniert' ...
Objektnotation mit Nullen
Nebenbei bemerkt, wenn Sie den Prototyp von Array ändern, beides
und
wird diese Prototyp-Modifikationen haben
Auf jeden Fall würde ich mich nicht allzu sehr um die Effizienz oder Geschwindigkeit dieses Vorgangs kümmern. Es gibt viele andere Dinge, die Sie wahrscheinlich tun werden, die weitaus verschwenderischer und teurer sind, als ein Array beliebiger Länge mit Nullen zu instanziieren.
quelle
null
s in diesem Array -var x = new Array(7);
new Array(7)
ist nicht ein Array „gefüllt mit undefinierten“ erstellen. Es erstellt ein leeres Array mit der Länge 7.(new Array(10)).fill(0)
.Ich habe in IE 6/7/8, Firefox 3.5, Chrome und Opera alle Kombinationen von Vorzuweisung / Nichtvorzuweisung, Aufwärts- / Abwärts- und For / While-Schleifen getestet.
Die folgenden Funktionen waren in Firefox, Chrome und IE8 durchweg die schnellsten oder extremsten und in Opera und IE 6 nicht viel langsamer als die schnellsten. Sie sind meiner Meinung nach auch die einfachsten und klarsten. Ich habe mehrere Browser gefunden, in denen die while-Schleifenversion etwas schneller ist, daher füge ich sie auch als Referenz hinzu.
oder
quelle
var array = []
Deklaration auch in den ersten Teil der for-Schleife werfen, der nur durch ein Komma getrennt ist.length
bereits angegebenen Wert ein, damit es sich nicht ständig ändert. Brachte ein 1 Million langes Array von Nullen von 40 ms bis 8 auf meinen Computer.for (i = 0, array = []; i < length; ++i) array[i] = val;
.. Weniger Blöcke? ... jedenfalls auch ... wenn icharray.length
das neue Array auf die Länge setze ... ich bekomme eine weitere Geschwindigkeitssteigerung von 10% -15% in FF ... in Chrome scheint es die Geschwindigkeit zu verdoppeln ->var i, array = []; array.length = length; while(i < length) array[i++] = val;
(war immer noch schneller, wenn ich es alsfor
Schleife belassen habe ... aber der Init wird nicht mehr benötigt, so dass derwhile
bei dieser Version scheinbar schneller ist)Wenn Sie während der Ausführung Ihres Codes viele mit Nullen gefüllte Arrays unterschiedlicher Länge erstellen müssen, besteht der schnellste Weg, dies zu erreichen, darin, einmal mit einer der in diesem Thema genannten Methoden ein Null-Array mit einer Länge zu erstellen von denen Sie wissen, dass sie niemals überschritten werden, und schneiden Sie das Array dann nach Bedarf auf.
Erstellen Sie beispielsweise (unter Verwendung der Funktion aus der oben gewählten Antwort zum Initialisieren des Arrays) ein mit Null gefülltes Array mit der Länge maxLength als Variable, die für den Code sichtbar ist, der Null-Arrays benötigt:
Schneiden Sie dieses Array jetzt jedes Mal in Scheiben, wenn Sie ein mit Null gefülltes Array mit der erforderlichen Länge benötigen. Länge < maxLänge :
Ich habe während der Ausführung meines Codes tausende Male null gefüllte Arrays erstellt, was den Prozess enorm beschleunigte.
quelle
quelle
new Array(size+1).join("x").split("x").map(function() { return 0; })
, um tatsächliche Zahlen zu erhaltennew Array(size+1).join('0').split('').map(Number)
Ich habe nichts gegen:
Von Zertosh vorgeschlagen, aber in einer neuen ES6- Array-Erweiterung können Sie dies nativ mit der
fill
Methode tun . Jetzt unterstützen IE Edge, Chrome und FF dies, überprüfen Sie jedoch die Kompatibilitätstabellenew Array(3).fill(0)
werde dir geben[0, 0, 0]
. Sie können das Array mit einem beliebigen Wert wienew Array(5).fill('abc')
(auch Objekten und anderen Arrays) füllen .Darüber hinaus können Sie vorherige Arrays mit fill ändern:
was dir gibt:
[1, 2, 3, 9, 9, 6]
quelle
Die Art und Weise, wie ich es normalerweise mache (und es ist erstaunlich schnell), ist die Verwendung
Uint8Array
. Beispiel: Erstellen eines mit Nullen gefüllten Vektors aus 1 Millionen Elementen:Ich bin ein Linux-Benutzer und habe immer für mich gearbeitet, aber einmal hatte ein Freund, der einen Mac verwendete, einige Elemente ungleich Null. Ich dachte, seine Maschine funktioniert nicht richtig, aber hier ist der sicherste Weg, dies zu beheben:
Bearbeitet
Chrome 25.0.1364.160
Firefox 20.0
Ich vermisse den wichtigsten Test (zumindest für mich): den Node.js. Ich vermute, dass es nahe am Chrome-Benchmark liegt.
quelle
Mit lodash oder Unterstrich
Oder wenn ein Array vorhanden ist und Sie ein Array mit derselben Länge möchten
quelle
_.range(0, length, 0)
, glaube ich. Lodash ist exklusiv vom EndwertES6-Lösung:
quelle
Ab ECMAScript2016 gibt es eine klare Wahl für große Arrays.
Da diese Antwort bei Google-Suchanfragen immer noch ganz oben angezeigt wird, finden Sie hier eine Antwort für 2017.
Hier ist eine aktuelle jsbench mit ein paar Dutzend gängigen Methoden, darunter viele, die bisher zu dieser Frage vorgeschlagen wurden. Wenn Sie eine bessere Methode finden, fügen Sie diese bitte hinzu, teilen Sie sie und teilen Sie sie.
Ich möchte darauf hinweisen, dass es keinen wirklich effizientesten Weg gibt, ein Array mit beliebiger Länge und Null zu erstellen. Sie können die Geschwindigkeit oder die Klarheit und Wartbarkeit optimieren - je nach den Anforderungen des Projekts kann entweder die effizientere Wahl getroffen werden.
Bei der Optimierung der Geschwindigkeit möchten Sie: das Array mithilfe der Literal-Syntax erstellen; Legen Sie die Länge fest, initialisieren Sie die iterierende Variable und durchlaufen Sie das Array mithilfe einer while-Schleife. Hier ist ein Beispiel.
Eine andere mögliche Implementierung wäre:
Ich rate jedoch dringend davon ab, diese zweite Implantation in der Praxis zu verwenden, da sie weniger klar ist und es Ihnen nicht ermöglicht, das Block-Scoping für Ihre Array-Variable beizubehalten.
Diese sind deutlich schneller als das Füllen mit einer for-Schleife und etwa 90% schneller als die Standardmethode von
Diese Füllmethode ist jedoch aufgrund ihrer Klarheit, Prägnanz und Wartbarkeit immer noch die effizienteste Wahl für kleinere Arrays. Der Leistungsunterschied wird Sie wahrscheinlich nicht töten, wenn Sie nicht viele Arrays mit Längen in der Größenordnung von Tausenden oder mehr erstellen.
Ein paar andere wichtige Hinweise. Die meisten Styleguides empfehlen, dass Sie
var
ES6 oder höher nicht ohne besonderen Grund mehr verwenden . Verwendungconst
für Variablen, die nicht neu definiert werden, undlet
für Variablen, die neu definiert werden. Das MDN und der Airbnb Style Guide sind großartige Orte, um weitere Informationen zu Best Practices zu erhalten. Bei den Fragen ging es nicht um Syntax, aber es ist wichtig, dass JS-Neulinge diese neuen Standards kennen, wenn sie diese Unmengen alter und neuer Antworten durchsuchen.quelle
So erstellen Sie ein völlig neues Array
Hinzufügen einiger Werte am Ende eines vorhandenen Arrays
[...existingArray, ...new Array(numberOfElementsToAdd).fill(0)]
Beispiel
quelle
Ich habe diese Methode nicht in Antworten gesehen, also hier ist sie:
Als Ergebnis erhalten Sie ein nullwertiges Array mit einer Länge von 200:
Ich bin mir über die Leistung dieses Codes nicht sicher, aber es sollte kein Problem sein, wenn Sie ihn für relativ kleine Arrays verwenden.
quelle
quelle
Diese
concat
Version ist in meinen Tests auf Chrome (21.03.2013) viel schneller. Etwa 200 ms für 10.000.000 Elemente gegenüber 675 für Straight Init.Bonus: Wenn Sie Ihr Array mit Strings füllen möchten, ist dies eine kurze Möglichkeit (nicht ganz so schnell wie
concat
):quelle
Ich habe die großartige Antwort von TJ Crowder getestet und eine rekursive Zusammenführung gefunden, die auf der Concat-Lösung basiert, die alle seine Tests in Chrome übertrifft (ich habe keine anderen Browser getestet).
Rufen Sie die Methode mit auf
makeRec(29)
.quelle
Was ist mit
new Array(51).join('0').split('')
?quelle
.map(function(a){return +a})
?Es könnte erwähnenswert sein, dass
Array.prototype.fill
dies als Teil des ECMAScript 6 (Harmony) -Vorschlags hinzugefügt wurde . Ich würde mich lieber für die unten beschriebene Polyfüllung entscheiden, bevor ich andere im Thread erwähnte Optionen in Betracht ziehe.quelle
Am kürzesten für Schleifencode
Sichere var-Version
quelle
n
, wäre diese kürzer:for(var a=[];n--;a[n]=0);
quelle
Meine schnellste Funktion wäre:
Das native Drücken und Verschieben zum Hinzufügen von Elementen zum Array ist viel schneller (ungefähr zehnmal) als das Deklarieren des Array-Bereichs und das Referenzieren jedes Elements, um seinen Wert festzulegen.
fyi: Ich bekomme durchweg schnellere Zeiten mit der ersten Schleife, die herunterzählt, wenn ich diese in Firebug (Firefox-Erweiterung) ausführe.
Ich bin interessiert zu wissen, was TJ Crowder daraus macht. :-)
quelle
while (len--)
... ändern . Ich habe meine Verarbeitungszeiten von ungefähr 60 ms auf ungefähr 54Ich wusste, dass ich dieses Proto irgendwo hatte :)
Bearbeiten: Tests
Als Reaktion auf Joshua und andere Methoden habe ich mein eigenes Benchmarking durchgeführt und sehe völlig andere Ergebnisse als die gemeldeten.
Folgendes habe ich getestet:
Ergebnisse:
Meiner Meinung nach ist Push zwar im Allgemeinen langsamer, schneidet aber bei längeren Arrays in FF besser ab, im IE jedoch schlechter, was im Allgemeinen nur zum Kotzen ist (Quel-Überraschung).
quelle
b = []...
) ist 10-15% schneller als die erste, aber mehr als zehnmal langsamer als Joshuas Antwort.else {this.length=n;}
nach demthis.length
Check ein. Dadurch wird ein bereits vorhandenes Array bei Bedarf verkürzt, wenninit
es auf eine andere Länge neu initialisiert wirdn
.Anonyme Funktion:
Etwas kürzer mit for-Schleife:
Funktioniert mit jedem
Object
, ändern Sie einfach, was drin istthis.push()
.Sie können die Funktion sogar speichern:
Nennen Sie es mit:
Hinzufügen von Elementen zu einem bereits vorhandenen Array:
Leistung: http://jsperf.com/zero-filled-array-creation/25
quelle