Ich suche nach Alternativen zu den folgenden, um ein JavaScript-Array mit 1 bis N zu erstellen, wobei N nur zur Laufzeit bekannt ist.
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
Für mich scheint es einen Weg zu geben, dies ohne die Schleife zu tun.
javascript
arrays
Götter
quelle
quelle
1 ... N
?Antworten:
Wenn ich bekomme, wonach Sie suchen, möchten Sie eine Reihe von Zahlen
1..n
, die Sie später durchlaufen können.Wenn dies alles ist, was Sie brauchen, können Sie dies stattdessen tun?
dann, wenn Sie es verwenden möchten ... (nicht optimiert, nur zum Beispiel)
Wenn Sie beispielsweise nichts im Array speichern müssen, benötigen Sie nur einen Container mit der richtigen Länge, über den Sie iterieren können. Dies ist möglicherweise einfacher.
Sehen Sie es hier in Aktion: http://jsfiddle.net/3kcvm/
quelle
var n = 45;
und dann Schleife von1..n
würde reichen.foo.length = M
--- Die abgeschnittenen Informationen gehen verloren. Sehen Sie es in Aktion ==> jsfiddle.net/ACMXpvar n = 45;
.new Array(45);
dies kein "45-Elemente-Array" erzeugt (in der gleichen Bedeutung wie[undefined,undefined,..undefined]
). Es wird eher "ein leeres Array mit einer Länge von 45" erstellt ([undefined x 45]
), genau wievar foo = []; foo.length=45;
. Das ist der GrundforEach
undmap
gilt in diesem Fall nicht.In ES6 mit den Methoden Array from () und keys () .
Kürzere Version mit Spread-Operator .
quelle
map
mit dem Array verketten, um die Werte ([...Array(10).keys()].map(x => x++);
) anzupassen , um bei 1 zu beginnenmap(x => x++)
aufmap(x => ++x)
aufgrund der Priorität Inkrement erfolgt nach dermap
wenn Sie einfach könnenslice
?[...Array(N+1).keys()].slice(1)
keys
und nur 1 Karte ->Array.from(Array(10)).map((e,i)=>i+1)
from
Array.from(Array(10), (e,i)=>i+1)
Sie können dies tun:
oder mit zufälligen Werten:
Erläuterung
Beachten Sie zunächst, dass dies
Number.call(undefined, N)
äquivalent zu istNumber(N)
, was gerade zurückgegeben wirdN
. Wir werden diese Tatsache später nutzen.Array.apply(null, [undefined, undefined, undefined])
ist äquivalent zuArray(undefined, undefined, undefined)
, das ein Array mit drei Elementen erzeugt undundefined
jedem Element zuweist .Wie kann man das auf N Elemente verallgemeinern ? Überlegen Sie, wie es
Array()
funktioniert, was ungefähr so aussieht:Da ECMAScript 5 ,
Function.prototype.apply(thisArg, argsArray)
akzeptiert auch eine Ente typisierte Array-ähnliches Objekt als zweiten Parameter. Wenn wir aufrufenArray.apply(null, { length: N })
, wird es ausgeführtJetzt haben wir ein N- Element-Array, auf das jedes Element gesetzt ist
undefined
. Wenn wir es aufrufen.map(callback, thisArg)
, wird jedes Element auf das Ergebnis von gesetztcallback.call(thisArg, element, index, array)
. Daher[undefined, undefined, …, undefined].map(Number.call, Number)
würde jedes Element zugeordnet werden(Number.call).call(Number, undefined, index, array)
, was dasselbe istNumber.call(undefined, index, array)
, das, wie wir zuvor beobachtet haben, ausgewertet wirdindex
. Damit ist das Array vervollständigt, dessen Elemente mit ihrem Index übereinstimmen.Warum sich die Mühe machen
Array.apply(null, {length: N})
anstatt nurArray(N)
? Schließlich würden beide Ausdrücke ein N- Element-Array undefinierter Elemente ergeben. Der Unterschied ist , dass in dem früheren Ausdruck, wobei jedes Element explizit gesetzt zu undefinierten, wohingegen in den letzteren, wobei jedes Element nie gesetzt wurde. Nach der Dokumentation von.map()
:Daher
Array(N)
ist nicht ausreichend;Array(N).map(Number.call, Number)
würde zu einem nicht initialisierten Array der Länge N führen .Kompatibilität
Da diese Technik auf dem
Function.prototype.apply()
in ECMAScript 5 angegebenen Verhalten beruht , funktioniert sie in Browsern vor ECMAScript 5 wie Chrome 14 und Internet Explorer 9 nicht.quelle
Function.prototype.call
der erste Parameter dasthis
Objekt ist, das direkt überArray.prototype.map
den Iteratorparameter abgebildet werden soll, hat eine gewisse Brillanz.map
meiner Meinung nach die Eigenart nicht zugewiesener Werte. Eine andere Version (und möglicherweise etwas klarer, wenn auch länger) ist:Array.apply(null, { length: N }).map(function(element, index) { return index; })
Array.apply(null, new Array(N)).map(function(_,i) { return i; })
oder, im Fall von es6- und Pfeilfunktionen, noch kürzer:Array.apply(null, new Array(N)).map((_,i) => i)
Mehrere Möglichkeiten mit ES6
Verwenden des Spread-Operators (
...
) und der Keys-MethodeFüllen / Karte
Array.from
Array.from und
{ length: N }
hackHinweis zur verallgemeinerten Form
Alle Formen oben produzieren können Arrays initialisiert ziemlich jede gewünschten Wert durch Änderung
i+1
erforderlich ist, um die Expression (beispielsweisei*2
,-i
,1+i*2
,i%2
und etc.). Wenn Ausdruck durch eine Funktion ausgedrückt werden kann, wirdf
die erste Form einfachBeispiele:
Da das Array initialisiert wird
undefined
an jeder Position, der Wertv
wirdundefined
Beispiel für alle Formulare
Code-Snippet anzeigen
Allgemeineres Beispiel mit Funktion benutzerdefinierten initialiser
f
dhoder noch einfacher
Code-Snippet anzeigen
quelle
k++
, verwenden Sie++k
.Arrays verwalten von Natur aus ihre Längen. Während sie durchlaufen werden, können ihre Indizes im Speicher gehalten und an diesem Punkt referenziert werden. Wenn ein Zufallsindex bekannt sein muss, kann die
indexOf
Methode verwendet werden.Für Ihre Anforderungen möchten Sie möglicherweise nur ein Array mit einer bestimmten Größe deklarieren:
ES6
Ausbreitung
Mithilfe des Spread-Operators (
...
) und derkeys
Methode können Sie ein temporäres Array der Größe N erstellen, um die Indizes zu erstellen, und anschließend ein neues Array, das Ihrer Variablen zugewiesen werden kann:Füllen / Karte
Sie können zuerst die Größe des Arrays erstellen, das Sie benötigen, es mit undefiniert füllen und dann mit ein neues Array erstellen
map
, das jedes Element auf den Index setzt.Array.from
Dies sollte auf die Länge der Größe N initialisiert und das Array in einem Durchgang gefüllt werden.
Anstelle der Kommentare und der Verwirrung gibt es einige Optionen, wenn Sie die Werte von 1..N in den obigen Beispielen wirklich erfassen möchten:
++i
. B. ).In Fällen, in denen der Index nicht verwendet wird - und möglicherweise auf effizientere Weise -, müssen Sie Ihr Array erstellen, aber N für N + 1 stellen und dann die Vorderseite verschieben.
Wenn Sie also 100 Zahlen wünschen:
quelle
In ES6 können Sie Folgendes tun:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Bearbeiten: Geändert
Array(45)
zu,Array(N)
seit Sie die Frage aktualisiert haben.quelle
.join.split
Version - aber ich denke immer noch, dass die bescheidene Schleife besser ist.map
bald ein Standard für solche Dinge werden wird.const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
.fill()
das notwendig ist. Ich sehe, dass es ist, wenn ich die Antwort des Knotens teste, aber seitdemArray(1)[0] === undefined
, welchen Unterschied macht der Aufruf von fill () inArray(1).fill(undefined)
?Verwenden Sie die sehr beliebte Methode Underscore _.range
quelle
Dann angerufen von
Es gibt keine integrierte Möglichkeit, dies in Javascript zu tun, aber es ist eine vollkommen gültige Dienstprogrammfunktion, die Sie erstellen können, wenn Sie sie mehrmals ausführen müssen.
Bearbeiten: Meiner Meinung nach ist das Folgende eine bessere Bereichsfunktion. Vielleicht nur, weil ich von LINQ voreingenommen bin, aber ich denke, dass es in mehr Fällen nützlicher ist. Ihr Kilometerstand kann variieren.
quelle
Array
statt ,Array.prototype
da es keinen Grund (es sogar eher dumm angesehen werden könnte) auf jedem Array diese Methode zu haben.Array.range(1, 5)
wäre wahrscheinlich angemessener, aber das Schreiben hat etwas Cooles[].range(1, 5)
.foo = [1, 2, 3]; bar = foo.range(0, 10);
. Aber das ist nur ... verwirrend.bar = Array.range(0, 10)
ist viel klarer und expliziter. Der Bereich hat nichts mit der Instanz zu tun, daher gibt es keinen Grund, sie zu einer Instanzmethode zu machen.Der schnellste Weg, eine
Array
Version 8 auszufüllen, ist:Ergebnis wird sein:
[0, 1, 2, 3, 4]
quelle
Diese Frage hat viele komplizierte Antworten, aber einen einfachen Einzeiler:
Auch wenn das Obige kurz (und ordentlich) zu schreiben ist, denke ich, dass das Folgende etwas schneller ist (für eine maximale Länge von:
127, Int8,
255, Uint8,
32,767, Int16,
65,535, Uint16,
2,147,483,647, Int32,
4,294,967,295, Uint32.
(basierend auf den maximalen Ganzzahlwerten ), auch hier mehr zu typisierten Arrays ):
Obwohl diese Lösung auch nicht so ideal ist, weil sie zwei Arrays erstellt und die zusätzliche Variablendeklaration "$" verwendet (nicht sicher, wie man das mit dieser Methode umgehen kann). Ich denke, die folgende Lösung ist der absolut schnellste Weg, dies zu tun:
Nach dieser Anweisung können Sie jederzeit die Variable "arr" im aktuellen Bereich verwenden.
Wenn Sie eine einfache Funktion daraus machen möchten (mit einigen grundlegenden Überprüfungen):
Mit der obigen Funktion wird der obige super langsame "einfache Einzeiler" zum superschnellen, sogar kürzeren:
quelle
fill
Methode:Array(255).fill(0,0,255)
Sie können dies verwenden:
zum Beispiel
erstellt folgendes Array:
quelle
new Array(10).join().split(',').map(function() {return ++arguments[1]});
?join
, einmal zusplit
und einmal für das, was Sie tatsächlich tun möchten), ist einfach nicht schön - ich weiß, dass sie in Ungnade gefallen zu sein scheinen aus irgendeinem Grund, aber es wäre weitaus besser, einfach eine gute altmodische Schleife zu verwenden !ES6 das wird den Trick machen:
Überprüfen Sie das Ergebnis:
quelle
[...Array(N + 1).keys()].slice(1)
wird 1..N ergeben[...Array(N + 1).keys()]
Dieser Code gibt ein leeres Array zurück, aber nur im Produktionsmodus funktioniert die Verwendung des Entwicklungsmodus..keys()
Antwort wurde bereits vor Jahren gegeben und hat mehr als 500 positive Stimmen. Was trägt Ihre Antwort dazu bei?Wenn Sie zufällig d3.js verwenden in Ihrer App verwenden, wie ich es bin, bietet D3 eine , die dies für Sie erledigt.
Um ein Array von 0 bis 4 zu erhalten, ist es so einfach wie:
und um ein Array von 1 bis 5 zu erhalten, wie Sie es angefordert haben:
Weitere Informationen finden Sie in diesem Tutorial .
quelle
Verwenden des Spread-Operators ES2015 / ES6
quelle
i + 1
würde mehr Sinn machen als++i
.Dies ist wahrscheinlich der schnellste Weg, um ein Array von Zahlen zu generieren
Kürzeste
In der Reihe
Wenn Sie von 1 beginnen möchten
Willst du eine Funktion?
WARUM?
while
ist die schnellste SchleifeDirekte Einstellung ist schneller als
push
[]
ist schneller alsnew Array(10)
es ist kurz ... schau dir den ersten Code an. Dann schauen Sie sich alle anderen Funktionen hier an.
Wenn Sie mögen , kann nicht leben , ohne für
oder
quelle
console.time()
, um eine Intuition zu bekommen, aber für einen Beweis benötigen Sie jsperf.com UND es zeigt Ihnen browserübergreifende Ergebnisse von anderen Personen (andere Hardware usw.)var a=[],b=N;while(b--){a[b]=a+1};
Der neue Weg zum Füllen
Array
ist:Ergebnis wird sein:
[0, 1, 2, 3, 4]
quelle
Wenn Sie lodash verwenden, können Sie _.range verwenden :
Beispiele:
quelle
Mit ES6 können Sie Folgendes tun:
quelle
map
undforEach
funktionieren.Abschlussbericht .. Drrruummm Rolll -
Dies ist der kürzeste Code zum Generieren eines Arrays der Größe N (hier 10) ohne Verwendung von ES6 . Die obige Version von Cocco ist nah, aber nicht die kürzeste.
Der unbestrittene Gewinner dieses Code-Golfs (Wettbewerb zur Lösung eines bestimmten Problems in den wenigsten Bytes des Quellcodes) ist Niko Ruotsalainen . Verwenden des Array-Konstruktors und des ES6-Spread-Operators . (Der größte Teil der ES6-Syntax ist gültiges TypeScript, das Folgende jedoch nicht. Seien Sie also bei der Verwendung vorsichtig.)
quelle
a
. Die Schleife sollte seinfor(var a=[];n--;a[n]=n+1)
Es gibt eine andere Möglichkeit in ES6, Array.from zu verwenden, das zwei Argumente akzeptiert. Das erste ist ein arrayLike (in diesem Fall ein Objekt mit
length
Eigenschaft) und das zweite ist eine Zuordnungsfunktion (in diesem Fall ordnen wir das Element seinem Index zu).Dies ist kürzer und kann für andere Sequenzen wie das Generieren von geraden Zahlen verwendet werden
Dies hat auch eine bessere Leistung als die meisten anderen Methoden, da es das Array nur einmal durchläuft. Überprüfen Sie das Snippit für einige Vergleiche
quelle
Array.from({length:N}, (v,i) => i+1)
Verwenden neuer Array-Methoden und
=>
Funktionssyntax aus dem ES6-Standard (zum Zeitpunkt des Schreibens nur Firefox).Durch Füllen von Löchern mit
undefined
:Array.from
verwandelt "Löcher" inundefined
soArray.map
funktioniert wie erwartet:quelle
Array.from({length: N}, (v, k) => k)
.Array.prototype.map.call
z. B. für NodeLists zurückzugreifen, von denen zurückgegeben wirddocument.querySelectorAll
. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…Array.from
was die spärlichen Werte in undefiniert verwandelt. EherArray(5)
wird als Argumentobjekt aufgerufen, das wiederum die spärlichen Werte als undefinierte Werte interpretiert :)quelle
[...Array(9)].map((_, i) => i)
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
quelle
In ES6:
ES5:
quelle
Nur ein weiterer ES6 Version.
Unter Verwendung des
Array.from
zweiten optionalen Arguments:Wir können das nummerierte Array aus den leeren
Array(10)
Positionen erstellen :quelle
[...Array(11).keys()].slice(1)
.Es scheint, dass der einzige Geschmack, der derzeit nicht in dieser ziemlich vollständigen Liste von Antworten enthalten ist, ein Generator ist. um dem abzuhelfen:
welches so verwendet werden kann:
Das Schöne daran ist, dass Sie nicht nur inkrementieren müssen ... Um sich von der Antwort von igor-shubin inspirieren zu lassen, können Sie ganz einfach eine Reihe von Zufällen erstellen:
Und anstatt etwas
langwierigoperativ teures wie:Sie könnten stattdessen tun:
quelle
Sie können Array Fill und Map von Es6 aus verwenden. Genau wie einige wenige Leute in den Antworten vorgeschlagen haben, die sie auf diese Frage gegeben haben. Nachfolgend einige Beispiele:
Ich bevorzuge dies, weil ich es einfach und einfacher finde.
quelle
Quelle: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
quelle
Verwenden von ES6
quelle
Array.from(Array(n))
wenn der Spread-Operator nicht unterstützt wird.map
MDN : "Es wird nicht für fehlende Elemente des Arrays aufgerufen (dh Indizes, die noch nie gesetzt wurden, die haben gelöscht wurde oder denen noch nie ein Wert zugewiesen wurde). "Object.keys(Array.apply(0, Array(3))).map(Number)
Rückgabe
[0, 1, 2]
. Sehr ähnlich zu Igor Shubins ausgezeichneter Antwort , aber mit etwas weniger Tricks (und einem Charakter länger).Erläuterung:
Array(3) // [undefined × 3]
Generieren Sie ein Array mit der Länge n = 3. Leider ist dieses Array für uns fast nutzlos, also müssen wir…Array.apply(0,Array(3)) // [undefined, undefined, undefined]
Machen Sie das Array iterierbar. Hinweis: Null ist häufiger als das erste Argument von apply, aber 0 ist kürzer.Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']
Holen Sie sich dann die Schlüssel des Arrays (funktioniert, weil Arrays der Typ des Arrays sind, ist ein Objekt mit Indizes für Schlüssel.Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]
und ordnen Sie die Tasten zu und konvertieren Sie Zeichenfolgen in Zahlen.quelle