So erstellen Sie ein Array mit 1… N.

1163

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.

Götter
quelle
224
Nachdem ich diese ganze Seite gelesen habe, bin ich zu dem Schluss gekommen, dass Ihre eigene einfache for-Schleife die einfachste, am besten lesbare und am wenigsten fehleranfällige ist.
Kokodoko
Wenn jemand etwas Fortgeschritteneres benötigt, habe ich eine node.js-Bibliothek erstellt, die dies für Zahlen, Buchstaben, negative / positive Bereiche usw. tut . Github.com/jonschlinkert/fill-range . Es wird in github.com/jonschlinkert/braces für die
Klammererweiterung
1
Sie sollten bearbeiten, um zu sagen, "Wie man ein Array der Länge N erstellt" anstelle von "... enthält 1 ... N". Letzteres impliziert, dass es Elemente mit Werten von 1 bis N gibt
Steven Landow
7
@StevenLandow warum sollte OP umbenennen? Er will ein Array mit Werten 1 ... N?
Andre Elrico
Gute Frage, guter Titel, (irgendwie) dumme Antworten.
Bitterblue

Antworten:

381

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?

var foo = new Array(45); // create an empty array with length 45

dann, wenn Sie es verwenden möchten ... (nicht optimiert, nur zum Beispiel)

for(var i = 0; i < foo.length; i++){
  document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>'); 
}

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/

scunliffe
quelle
4
beeindruckt, dass Sie es geschafft haben, meine Frage besser zu formulieren als ich, Sie haben in der Tat Recht, denn alles, was ich zum Nachdenken brauche, ist eine Reihe von Zahlen, die ich später durchlaufen kann :) Vielen Dank für Ihre Antwort.
Godders
147
@Godders: Wenn du danach suchst, warum brauchst du dann ein Array? Eine einfache var n = 45;und dann Schleife von 1..nwürde reichen.
Casablanca
3
@Godders - Wenn Sie die Größe des Arrays nach dem Erstellen auf Länge M verringern möchten, verwenden Sie einfach foo.length = M--- Die abgeschnittenen Informationen gehen verloren. Sehen Sie es in Aktion ==> jsfiddle.net/ACMXp
Peter Ajtai
24
Ich verstehe wirklich nicht, warum diese Antwort überhaupt positive Stimmen hat ... besonders wenn der OP selbst zustimmt, dass es in einigen Kommentaren oben keinen Sinn ergibt, da er es einfach hätte tun können var n = 45;.
Plalx
72
@scunliffe: Bitte beachten Sie, dass 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 wie var foo = []; foo.length=45;. Das ist der Grund forEachund mapgilt in diesem Fall nicht.
Tomalec
1309

In ES6 mit den Methoden Array from () und keys () .

Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Kürzere Version mit Spread-Operator .

[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Niko Ruotsalainen
quelle
75
Nur eine Anmerkung, dies wird immer bei 0 beginnen. Muss ein mapmit dem Array verketten, um die Werte ( [...Array(10).keys()].map(x => x++);) anzupassen , um bei 1 zu beginnen
Sterling Archer
32
Ändern Sie einfach map(x => x++)auf map(x => ++x)aufgrund der Priorität Inkrement erfolgt nach der
Brock
93
Äh was!? Warum, mapwenn Sie einfach können slice? [...Array(N+1).keys()].slice(1)
Robin
19
Oder nicht verwenden keysund nur 1 Karte ->Array.from(Array(10)).map((e,i)=>i+1)
yonatanmn
60
Oder verwenden Sie keine Schlüssel und keine Karte und übergeben Sie einfach eine Zuordnungsfunktion anfrom Array.from(Array(10), (e,i)=>i+1)
Fabio Antunes
844

Sie können dies tun:

var N = 10; 
Array.apply(null, {length: N}).map(Number.call, Number)

Ergebnis: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

oder mit zufälligen Werten:

Array.apply(null, {length: N}).map(Function.call, Math.random)

Ergebnis: [0,7082694901619107, 0,9572225909214467, 0,8586748542729765, 0,8653848143294454, 0,008339877473190427, 0,9911756622605026, 0,8133423360995948, 0,8377588465809822, 0,8377575

Erläuterung

Beachten Sie zunächst, dass dies Number.call(undefined, N)äquivalent zu ist Number(N), was gerade zurückgegeben wird N. Wir werden diese Tatsache später nutzen.

Array.apply(null, [undefined, undefined, undefined])ist äquivalent zu Array(undefined, undefined, undefined), das ein Array mit drei Elementen erzeugt und undefinedjedem Element zuweist .

Wie kann man das auf N Elemente verallgemeinern ? Überlegen Sie, wie es Array()funktioniert, was ungefähr so ​​aussieht:

function Array() {
    if ( arguments.length == 1 &&
         'number' === typeof arguments[0] &&
         arguments[0] >= 0 && arguments &&
         arguments[0] < 1 << 32 ) {
        return [  ];  // array of length arguments[0], generated by native code
    }
    var a = [];
    for (var i = 0; i < arguments.length; i++) {
        a.push(arguments[i]);
    }
    return a;
}

Da ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)akzeptiert auch eine Ente typisierte Array-ähnliches Objekt als zweiten Parameter. Wenn wir aufrufen Array.apply(null, { length: N }), wird es ausgeführt

function Array() {
    var a = [];
    for (var i = 0; i < /* arguments.length = */ N; i++) {
        a.push(/* arguments[i] = */ undefined);
    }
    return a;
}

Jetzt 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 gesetzt callback.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 ist Number.call(undefined, index, array), das, wie wir zuvor beobachtet haben, ausgewertet wird index. Damit ist das Array vervollständigt, dessen Elemente mit ihrem Index übereinstimmen.

Warum sich die Mühe machen Array.apply(null, {length: N})anstatt nur Array(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():

callbackwird nur für Indizes des Arrays aufgerufen, denen Werte zugewiesen wurden; Es wird nicht für Indizes aufgerufen, die gelöscht wurden oder denen nie Werte zugewiesen wurden.

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.

Igor Shubin
quelle
62
+1 für Klugheit, aber bitte beachten Sie, dass dies um Größenordnungen langsamer ist als ein Grundelement für Schleife: jsperf.com/array-magic-vs-for
Warpech
7
Sehr klug - wahrscheinlich auch. Das Ausnutzen der Tatsache, dass Function.prototype.callder erste Parameter das thisObjekt ist, das direkt über Array.prototype.mapden Iteratorparameter abgebildet werden soll, hat eine gewisse Brillanz.
Noah Freitas
14
Das ist wirklich sehr, sehr klug (grenzt an den Missbrauch von JS). Die wirklich wichtige Erkenntnis hier ist mapmeiner 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; })
Ben Reich
6
@ BenReich Noch besser (in Bezug auf JS-Missbrauchsstufen): 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)
seltsam
1
Wenn dies ein Array zurückgibt, das bei 1 beginnt, würde es tatsächlich die Frage des OP beantworten
Hai Phan
483

Mehrere Möglichkeiten mit ES6

Verwenden des Spread-Operators ( ...) und der Keys-Methode

[ ...Array(N).keys() ].map( i => i+1);

Füllen / Karte

Array(N).fill().map((_, i) => i+1);

Array.from

Array.from(Array(N), (_, i) => i+1)

Array.from und { length: N }hack

Array.from({ length: N }, (_, i) => i+1)

Hinweis zur verallgemeinerten Form

Alle Formen oben produzieren können Arrays initialisiert ziemlich jede gewünschten Wert durch Änderung i+1erforderlich ist, um die Expression (beispielsweise i*2, -i, 1+i*2, i%2und etc.). Wenn Ausdruck durch eine Funktion ausgedrückt werden kann, wird fdie erste Form einfach

[ ...Array(N).keys() ].map(f)

Beispiele:

Array.from({length: 5}, (v, k) => k+1); 
// [1,2,3,4,5]

Da das Array initialisiert wird undefinedan jeder Position, der Wert v wirdundefined

Beispiel für alle Formulare

Allgemeineres Beispiel mit Funktion benutzerdefinierten initialiser fdh

[ ...Array(N).keys() ].map((i) => f(i))

oder noch einfacher

[ ...Array(N).keys() ].map(f)

Abdennour TOUMI
quelle
33
Beste Antwort IMHO. Siehe auch developer.mozilla.org/de/docs/Web/JavaScript/Reference/…
le_m
5
Verwenden Sie k ++ für Arrays ab 0
Borgboy
1
Wenn Sie inkrementieren möchten, verwenden Sie nicht k++, verwenden Sie ++k.
Alex
4
Beachten Sie, dass Array.from im IE nicht unterstützt wird, es sei denn, Sie füllen es mehrfach aus.
Lauren
2
Um den TS-Compiler glücklich zu machen, sollten Sie den nicht verwendeten Parameter durch lodash ersetzen: Array.from ({length: 5}, (_, k) => k + 1);
Journeycorner
297

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 indexOfMethode verwendet werden.


Für Ihre Anforderungen möchten Sie möglicherweise nur ein Array mit einer bestimmten Größe deklarieren:

var foo = new Array(N);   // where N is a positive integer

/* this will create an array of size, N, primarily for memory allocation, 
   but does not create any defined values

   foo.length                                // size of Array
   foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array
*/


ES6

Ausbreitung

Mithilfe des Spread-Operators ( ...) und der keysMethode 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:

var foo = [ ...Array(N).keys() ];

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.

var foo = Array(N).fill().map((v,i)=>i);

Array.from

Dies sollte auf die Länge der Größe N initialisiert und das Array in einem Durchgang gefüllt werden.

Array.from({ length: N }, (v, i) => i)



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:

  1. Wenn der Index verfügbar ist, können Sie ihn einfach um eins erhöhen (z ++i. B. ).
  2. 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:

    let arr; (arr=[ ...Array(101).keys() ]).shift()




vol7ron
quelle
Ich glaube, dies ist nützlich, wenn das Array von Zahlen für Daten verwendet wird, die auf der Empfangsseite nicht verarbeitet werden können. (Wie eine HTML-Vorlage, die nur Werte ersetzt.)
Neil Monroe
Warum jemand dies tun würde, ist ein Array von Zahlen, um eine Dropdown-Liste zu füllen, sodass der Benutzer zwischen 1 und 10 wählen kann. Ein kleines Array von Hand [1,2,3 ... 10] ist sinnvoll, aber was ist, wenn es ist von 1 bis 50? Was ist, wenn sich die Endnummer ändert?
CigarDoug
@CigarDoug Ich bezweifle nicht, dass es einen Anwendungsfall gibt, aber ich denke, er ist klein. Warum sollte ein Array von Zahlen benötigt werden? Normalerweise wird beim Iterieren über ein Array ein Index als Teil des Schleifenkonstrukts verwendet - entweder als Argument für die Funktion des Schleifenkörpers oder als Zählervariable -, sodass das Halten des Arrays von Zahlen trivial erscheint um nur ein Array mit der angegebenen Breite oder nur eine Variable zu erstellen, die die Obergrenze des Arrays enthält. Ich kann mir einige Anwendungsfälle vorstellen, aber keiner davon wurde vom OP zum Ausdruck gebracht
vorstellen vol7ron
4
Wie gesagt, ich muss ein Dropdown mit den Zahlen 1 bis 10 füllen. Das ist alles. Es gibt einen Anwendungsfall, MEIN Anwendungsfall. So habe ich diese Seite gefunden. Das Erstellen eines Arrays von Hand war also weniger kompliziert als alles, was ich hier gesehen habe. Meine Anforderungen entsprechen also nicht den Anforderungen des OP. Aber ich habe meine Antwort.
CigarDoug
1
@ vol7ron Es gibt einen Anwendungsfall, ich habe auch einen. Im Winkel, beim Paging, möchte ich die Seiten in der Fußzeile anzeigen, auf die geklickt werden kann. Also schleife ich die Elemente in einer Ansicht mit * ngFor = "let p of pagesCounter". Sie haben eine bessere Lösung dafür? Übrigens, check out stackoverflow.com/questions/36354325/…
Dalibor
186

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.

console.log(
  Array(45).fill(0).map((e,i)=>i+1)
);

Nate
quelle
3
+1, weil es ein ganz großes O ist, besser als die böse .join.splitVersion - aber ich denke immer noch, dass die bescheidene Schleife besser ist.
Robin
Ich stimme @Robin zu - Abgesehen von der algorithmischen Komplexität ist die bescheidene Schleife immer besser lesbar. Mit dem Aufkommen von Lambdas in Java denke ich jedoch, dass dies mapbald ein Standard für solche Dinge werden wird.
Nate
4
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
Robin
8
Ich verstehe nicht, warum .fill()das notwendig ist. Ich sehe, dass es ist, wenn ich die Antwort des Knotens teste, aber seitdem Array(1)[0] === undefined, welchen Unterschied macht der Aufruf von fill () in Array(1).fill(undefined)?
Dominic
11
Für alle anderen, die interessiert sind, wird der Unterschied zwischen Array (N) und Array (N) .fill () hier
Dominic
108

Verwenden Sie die sehr beliebte Methode Underscore _.range

// _.range([start], stop, [step])

_.range(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5); // => [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1); //  => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0); // => []
Evan
quelle
Genial. Zeigen Sie mir ein großes Projekt, das sowieso keinen Unterstrich verwendet ...
Erez Cohen
63
function range(start, end) {
    var foo = [];
    for (var i = start; i <= end; i++) {
        foo.push(i);
    }
    return foo;
}

Dann angerufen von

var foo = range(1, 5);

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.

function range(start, count) {
    if(arguments.length == 1) {
        count = start;
        start = 0;
    }

    var foo = [];
    for (var i = 0; i < count; i++) {
        foo.push(start + i);
    }
    return foo;
}
Ian Henry
quelle
2
Ich mag das. Wenn Sie die Extrameile damit gehen möchten, können Sie es als Array.prototype.range = function (start, end) {...}; deklarieren. Anschließend können Sie den Bereich (x, y) für jedes Array-Objekt aufrufen.
Zach Rattner
8
Macht es eher ein Verfahren Arraystatt , Array.prototypeda es keinen Grund (es sogar eher dumm angesehen werden könnte) auf jedem Array diese Methode zu haben.
Adamse
9
Array.range(1, 5)wäre wahrscheinlich angemessener, aber das Schreiben hat etwas Cooles [].range(1, 5).
MooGoo
"Machen Sie es lieber zu einer Methode von Array anstelle von Array.prototype" - Was ist der Unterschied? Du meinst nur auf einem bestimmten Array?
Pilau
3
@pilau Genau wie Adamse sagt, sieht es komisch aus. Wenn es sich um den Prototyp handelt, können Sie sagen 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.
Ian Henry
53

Der schnellste Weg, eine ArrayVersion 8 auszufüllen, ist:

[...Array(5)].map((_,i) => i);

Ergebnis wird sein: [0, 1, 2, 3, 4]

alex dykyі
quelle
Gibt
@bluejayke no :(
alex dykyі
hart, weißt du was der Quellcode von .map ist? Ich bin nicht sicher, ob es schneller als eine for-Schleife ist, aber wenn nicht, können wir theoretisch einfach die Eigenschaft definieren und eine neue
erstellen
49

Diese Frage hat viele komplizierte Antworten, aber einen einfachen Einzeiler:

[...Array(255).keys()].map(x => x + 1)

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 ):

(new Uint8Array(255)).map(($,i) => i + 1);

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:

for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;

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):

function range(min, max) {
    min = min && min.constructor == Number ? min : 0;
    !(max && max.constructor == Number && max > min) && // boolean statements can also be used with void return types, like a one-line if statement.
        ((max = min) & (min = 0));  //if there is a "max" argument specified, then first check if its a number and if its graeter than min: if so, stay the same; if not, then consider it as if there is no "max" in the first place, and "max" becomes "min" (and min becomes 0 by default)

    for(var i = 0, arr = new (
        max < 128 ? Int8Array : 
        max < 256 ? Uint8Array :
        max < 32768 ? Int16Array : 
        max < 65536 ? Uint16Array :
        max < 2147483648 ? Int32Array :
        max < 4294967296 ? Uint32Array : 
        Array
    )(max - min); i < arr.length; i++) arr[i] = i + min;
    return arr;
}



//and you can loop through it easily using array methods if you want
range(1,11).forEach(x => console.log(x));

//or if you're used to pythons `for...in` you can do a similar thing with `for...of` if you want the individual values:
for(i of range(2020,2025)) console.log(i);

//or if you really want to use `for..in`, you can, but then you will only be accessing the keys:

for(k in range(25,30)) console.log(k);

console.log(
    range(1,128).constructor.name,
    range(200).constructor.name,
    range(400,900).constructor.name,
    range(33333).constructor.name,
    range(823, 100000).constructor.name,
    range(10,4) // when the "min" argument is greater than the "max", then it just considers it as if there is no "max", and the new max becomes "min", and "min" becomes 0, as if "max" was never even written
);


Mit der obigen Funktion wird der obige super langsame "einfache Einzeiler" zum superschnellen, sogar kürzeren:

range(1,14000);
Bluejayke
quelle
@JVG aber nicht für die schnellere Funktion?
Bluejayke
Genau richtig. Es ist dieser einfache Einzeiler, den jeder sucht!
Supersan
@supersan obwohl es super langsam ist :)
bluejayke
Modernes Javascript mit der neuen fillMethode:Array(255).fill(0,0,255)
Cacoder
@cacoder Wie schnell ist es, wie viele Arrays werden erstellt und wie viele Iterationen?
Bluejayke
42

Sie können dies verwenden:

new Array(/*any number which you want*/)
    .join().split(',')
    .map(function(item, index){ return ++index;})

zum Beispiel

new Array(10)
    .join().split(',')
    .map(function(item, index){ return ++index;})

erstellt folgendes Array:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nktssh
quelle
Warum auch nicht new Array(10).join().split(',').map(function() {return ++arguments[1]});?
Super
1
@ Murplyx für einige Fälle Funktion mit Argumenten im Inneren wird nicht von JS-Engine optimiert (wahr auch für V8, siehe jsperf.com/arguments-vs-array-argument/2 )
nktssh
4
Dies ist eine interessante Lösung, aber es ist völlig unpraktisch - das Array dreimal analysieren zu müssen (einmal zu join, einmal zu splitund 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 !
Robin
42

ES6 das wird den Trick machen:

[...Array(12).keys()]

Überprüfen Sie das Ergebnis:

[...Array(12).keys()].map(number => console.log(number))

Christian
quelle
5
Eigentlich fragten sie nach 1..N, nicht nach 0..N-1
YakovL
1
Ja, [...Array(N + 1).keys()].slice(1)wird 1..N ergeben
David G
Aus irgendeinem Grund funktioniert diese Lösung in der Produktionsversion der Expo-App (reaktionsnativ) nicht. [...Array(N + 1).keys()]Dieser Code gibt ein leeres Array zurück, aber nur im Produktionsmodus funktioniert die Verwendung des Entwicklungsmodus.
FabianoLothor
3
Die .keys()Antwort wurde bereits vor Jahren gegeben und hat mehr als 500 positive Stimmen. Was trägt Ihre Antwort dazu bei?
Dan Dascalescu
39

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:

d3.range(5)
[0, 1, 2, 3, 4]

und um ein Array von 1 bis 5 zu erhalten, wie Sie es angefordert haben:

d3.range(1, 5+1)
[1, 2, 3, 4, 5]

Weitere Informationen finden Sie in diesem Tutorial .

Tyler Rick
quelle
Dieser Kommentar brachte mich auf die Idee, die range () - Funktion in RamdaJS nachzuschlagen. Dies ist zufällig die JS-Bibliothek, mit der ich an meinem aktuellen Projekt arbeite. Perfekt.
Morphatic
39

Verwenden des Spread-Operators ES2015 / ES6

[...Array(10)].map((_, i) => i + 1)

console.log([...Array(10)].map((_, i) => i + 1))

Vlad Bezden
quelle
7
i + 1würde mehr Sinn machen als ++i.
Vincent Cantin
38

Dies ist wahrscheinlich der schnellste Weg, um ein Array von Zahlen zu generieren

Kürzeste

var a=[],b=N;while(b--)a[b]=b+1;

In der Reihe

var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]

Wenn Sie von 1 beginnen möchten

var arr=(function(a,b){while(a--)b[a]=a+1;return b})(10,[]);
//arr=[1,2,3,4,5,6,7,8,9,10]

Willst du eine Funktion?

function range(a,b,c){c=[];while(a--)c[a]=a+b;return c}; //length,start,placeholder
var arr=range(10,5);
//arr=[5,6,7,8,9,10,11,12,13,14]

WARUM?

  1. while ist die schnellste Schleife

  2. Direkte Einstellung ist schneller als push

  3. [] ist schneller als new Array(10)

  4. 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

for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]

oder

for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
cocco
quelle
8
Es wäre besser, diese Behauptungen mit Benchmarks zu untermauern. Versuchen Sie es mit jsperf.com .
Matt Ball
2
lol jsperf ... pls Matt, nur weil du meine Antwort nicht magst, hör auf, meine anderen herunterzustimmen ... stackoverflow.com/a/18344296/2450730 ... benutze console.time () oder wie es heißt ... NICHT jsperf .
Cocco
4
Zu Ihrer Information: Wie John Reisig vor einigen Jahren zum ersten Mal veröffentlichte - auf einigen Plattformen (dh Windows: P) wird dem Browser alle 16 ms Zeit zugeführt. Es gibt auch andere Probleme bei der Messung der Ausführungszeit in Multitasking-Umgebungen. jsperf.com hat die Ausführung der Tests implementiert, damit sie statistisch korrekt sind. Es ist in Ordnung zu laufen 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.)
naugtur
3
@cocco das ist falsch:var a=[],b=N;while(b--){a[b]=a+1};
vintagexav
5
@ cocco - während es nicht immer schneller ist als andere Loops. In einigen Browsern ist eine dekrementierende while-Schleife viel langsamer als eine for-Schleife. Sie können keine allgemeinen Aussagen über die Leistung von Javascript treffen, da es so viele Implementierungen mit so vielen verschiedenen Optimierungen gibt. Im Allgemeinen gefällt mir jedoch Ihr Ansatz. ;-)
RobG
32

Der neue Weg zum Füllen Arrayist:

const array = [...Array(5).keys()]
console.log(array)

Ergebnis wird sein: [0, 1, 2, 3, 4]

alex dykyі
quelle
Dies ist eine wirklich gute Antwort, obwohl die Frage technisch gesehen von 1-N war, nicht von 0- (N-1)
bluejayke
31

Wenn Sie lodash verwenden, können Sie _.range verwenden :

_.range([start=0], end, [step=1])

Erstellt ein Array von Zahlen (positiv und / oder negativ), die vom Start bis zum Ende reichen, diese jedoch nicht einschließen. Ein Schritt von -1 wird verwendet, wenn ein negativer Start ohne Ende oder Schritt angegeben wird. Wenn end nicht angegeben ist, beginnt es mit start und wird dann auf 0 gesetzt.

Beispiele:

_.range(4);
// ➜ [0, 1, 2, 3]

_.range(-4);
// ➜ [0, -1, -2, -3]

_.range(1, 5);
// ➜ [1, 2, 3, 4]

_.range(0, 20, 5);
// ➜ [0, 5, 10, 15]

_.range(0, -4, -1);
// ➜ [0, -1, -2, -3]

_.range(1, 4, 0);
// ➜ [1, 1, 1]

_.range(0);
// ➜ []
Hongbo Miao
quelle
30

Mit ES6 können Sie Folgendes tun:

// `n` is the size you want to initialize your array
// `null` is what the array will be filled with (can be any other value)
Array(n).fill(null)

quelle
Da die Werte des Arrays tatsächlich mit dieser Lösung gefüllt werden mapund forEachfunktionieren.
Dontmentionthebackup
27

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.

(function(n){for(a=[];n--;a[n]=n+1);return a})(10)

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.)

[...Array(10).keys()]
sapy
quelle
Warum abstimmen? Lange Antwortliste schwer zu folgen, also überlegte ich, sie zusammenzufassen.
Sapy
ist das nicht 0-10? [... Array (10) .keys ()]
Greg
Webstorm schlägt vor (neues Array (10)). Keys (), stimmt das?
Guy
(neues Array (10)). keys (), gibt ArrayIterator {} zurück, nicht das Array
sapy
Dadurch wird eine globale Variable erstellt a. Die Schleife sollte seinfor(var a=[];n--;a[n]=n+1)
kube
20

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 lengthEigenschaft) und das zweite ist eine Zuordnungsfunktion (in diesem Fall ordnen wir das Element seinem Index zu).

Array.from({length:10}, (v,i) => i)

Dies ist kürzer und kann für andere Sequenzen wie das Generieren von geraden Zahlen verwendet werden

Array.from({length:10}, (v,i) => i*2)

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

// open the dev console to see results

count = 100000

console.time("from object")
for (let i = 0; i<count; i++) {
  range = Array.from({length:10}, (v,i) => i )
}
console.timeEnd("from object")

console.time("from keys")
for (let i =0; i<count; i++) {
  range = Array.from(Array(10).keys())
}
console.timeEnd("from keys")

console.time("apply")
for (let i = 0; i<count; i++) {
  range = Array.apply(null, { length: 10 }).map(function(element, index) { return index; })
}
console.timeEnd("apply")

Gafi
quelle
Hey das ist ordentlich, ich mag es. Die von OP erwarteten Ergebnisse werden jedoch nicht zurückgegeben. Um dies zu tun, müsste es geschrieben werden alsArray.from({length:N}, (v,i) => i+1)
CervEd
Diese Neato-Hacks sind immer noch 5-10x langsamer als eine gute alte for-Schleife .
Dan Dascalescu
16

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(N).fill().map((_, i) => i + 1);

Array.fromverwandelt "Löcher" in undefinedso Array.mapfunktioniert wie erwartet:

Array.from(Array(5)).map((_, i) => i + 1)
szymzet
quelle
7
In ähnlicher Weise können Sie in ES6 auch Folgendes tun : Array.from({length: N}, (v, k) => k).
XåpplI'-I0llwlg'I -
Der Ansatz von Xappli wird bevorzugt: Array.from wurde für genau dieses Szenario erstellt und impliziert einen Mapping-Rückruf. Es ist eine hervorragende Lösung für das allgemeine Problem, Array-Methoden für etwas Array-ähnliches verwenden zu wollen, ohne auf ausführliche Ansätze wie Array.prototype.map.callz. B. für NodeLists zurückzugreifen, von denen zurückgegeben wird document.querySelectorAll. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Josh aus Qaribou
Ich wäge dies gegen die Unterstrichbereichssyntax ab, und der Bereich liest sich besser.
Ooolala
Technisch gesehen ist es nicht das, Array.fromwas die spärlichen Werte in undefiniert verwandelt. Eher Array(5)wird als Argumentobjekt aufgerufen, das wiederum die spärlichen Werte als undefinierte Werte interpretiert :)
CervEd
15

Array(...Array(9)).map((_, i) => i);

console.log(Array(...Array(9)).map((_, i) => i))

alex dykyі
quelle
Nett! Kann dies auch etwas prägnanter schreiben als[...Array(9)].map((_, i) => i)
Eamonn O'Brien-Strain
13
for(var i,a=[i=0];i<10;a[i++]=i);

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

SammieFox
quelle
Wirklich großartig! Tx!
Pedro Ferreira
12

In ES6:

Array.from({length: 1000}, (_, i) => i);

ES5:

Array.apply(0, {length: 1000}).map(function(x,i){return i});
Bluejayke
quelle
10

Nur ein weiterer ES6 Version.

Unter Verwendung des Array.fromzweiten optionalen Arguments:

Array.from (arrayLike [, mapFn [, thisArg]])

Wir können das nummerierte Array aus den leeren Array(10)Positionen erstellen :

Array.from(Array(10), (_, i) => i)

var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);

zurfyx
quelle
Dies ist komplizierter und ~ 10x langsamer als [...Array(11).keys()].slice(1).
Dan Dascalescu
10

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:

const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]

welches so verwendet werden kann:

gen(4) // [0,1,2,3]

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:

const gen = N => [...(function*(){let i=0;
  while(i++<N) yield Math.random()
})()]

Und anstatt etwas langwierig operativ teures wie:

const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]

Sie könnten stattdessen tun:

const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
Robin
quelle
10

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:

Example-One: Array(10).fill(0).map((e,i)=>i+1)

Result-One: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Example-Two: Array(100/10).fill(0).map((e,i)=>(i*10)+10)

Result-Two:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

Ich bevorzuge dies, weil ich es einfach und einfacher finde.

Gbemi Kadri
quelle
9

Verwenden von ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);
Geoffrey Abdallah
quelle
Vielen Dank! Dies war meiner Meinung nach die eleganteste Antwort! Man könnte es auch verwenden, Array.from(Array(n))wenn der Spread-Operator nicht unterstützt wird.
Amit
Zuerst wusste ich nicht, warum Sie den Spread-Operator verwenden mussten, aber dann las ich Folgendes über mapMDN : "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). "
Battmanz
9

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.
mluby
quelle