869 Stimmen

Der effizienteste Weg, um ein mit Nullen gefülltes JavaScript-Array zu erstellen?

Was ist der effizienteste Weg, um eine beliebige Länge Null gefüllt Array in JavaScript zu erstellen?

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

923voto

Oriol Punkte 246798

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 .

412voto

zertosh Punkte 5253

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]

183voto

Kamil Kiełczewski Punkte 69048

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 nicht push(..) 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 Arrays

    function P(n) {
      return Array.apply(null, Array(n)).map(Number.prototype.valueOf,0);
    }
    
    try {
      P(1000000);
    } catch(e) { 
      console.error(e.message);
    }

enter image description here

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:

enter image description here

133voto

Lucio Paiva Punkte 15969

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]

64voto

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X