Come creare un array contenente 1 ... N


1163

Sto cercando delle alternative a quelle seguenti per creare un array JavaScript contenente da 1 a N dove N è noto solo in fase di esecuzione.

var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

Per me sembra che ci dovrebbe essere un modo per farlo senza il ciclo.


224
Dopo aver letto l'intera pagina, sono giunto alla conclusione che il tuo semplice for-loop è il più semplice, più leggibile e meno soggetto a errori.
Kokodoko,

Se qualcuno ha bisogno di qualcosa di più avanzato, ho creato una libreria node.js che lo fa per numeri, lettere, intervalli negativi / positivi, ecc . Github.com/jonschlinkert/fill-range . È utilizzato in github.com/jonschlinkert/braces per l'espansione del controvento e github.com/jonschlinkert/micromatch per motivi glob
jonschlinkert

1
Dovresti modificare per dire "Come creare un array di lunghezza N" invece di "... contenente 1 ... N", quest'ultimo implica che ci saranno elementi con valori da 1 a N
Steven Landow

7
@StevenLandow perché rinominare OP? Vuole un array con valori 1 ... N?
Andre Elrico,

Bella domanda, buon titolo, (un pò) risposte sciocche.
Bitterblue,

Risposte:


381

Se ottengo ciò che cerchi, vuoi una serie di numeri 1..nche puoi successivamente ripetere.

Se è tutto ciò di cui hai bisogno, puoi farlo?

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

poi quando vuoi usarlo ... (non ottimizzato, solo per esempio)

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

ad esempio, se non è necessario archiviare nulla nell'array, è sufficiente un contenitore della lunghezza corretta su cui è possibile scorrere ... questo potrebbe essere più semplice.

Guardalo in azione qui: http://jsfiddle.net/3kcvm/


4
mi ha impressionato che sei riuscito a formulare la mia domanda meglio di quanto potessi, in effetti hai ragione, perché riflettendo tutto ciò di cui ho bisogno è una serie di numeri che posso in seguito scorrere in loop :) Grazie per la risposta.
Godders,

147
@Godders: se questo è ciò che stai cercando, perché hai bisogno di un array? Un semplice var n = 45;e quindi loop da 1..nfarebbe.
Casablanca,

3
@Godders - Da notare, se si desidera ridurre le dimensioni dell'array dopo che è stato creato alla lunghezza M, utilizzare semplicemente foo.length = M--- Le informazioni di interruzione vanno perse. Guardalo
Peter Ajtai

24
Non capisco davvero perché questa risposta abbia anche voti ... specialmente quando lo stesso PO concorda che non ha alcun senso in alcuni commenti sopra dato che avrebbe potuto fare var n = 45;.
Plalx,

72
@scunliffe: Nota che new Array(45);non "crea un array di 45 elementi" (nello stesso significato di come [undefined,undefined,..undefined]). Piuttosto "crea un array vuoto con lunghezza = 45" ( [undefined x 45]), lo stesso di var foo = []; foo.length=45;. Ecco perché forEach, e mapnon si applicherà in questo caso.
Tomalec,

1310

In ES6 si usano i metodi Array from () e keys () .

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

Versione più breve utilizzando l' operatore spread .

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

75
Solo una nota, questo inizierà sempre a 0. Dovrà legare mapa all'array per regolare i valori ( [...Array(10).keys()].map(x => x++);) per iniziare da 1
Sterling Archer

32
Basta passare map(x => x++)a map(x => ++x)causa dell'incremento della precedenza dopo il ritorno del valore :)
Brock,

93
Ehm cosa? Perché mapquando puoi semplicemente slice? [...Array(N+1).keys()].slice(1)
Robin,

19
Oppure non usare keyse solo 1 mappa ->Array.from(Array(10)).map((e,i)=>i+1)
yonatanmn

60
Oppure non usare i tasti e la mappa e passa semplicemente una funzione di mappatura afrom Array.from(Array(10), (e,i)=>i+1)
Fabio Antunes,

844

Puoi farlo:

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

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

o con valori casuali:

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

risultato: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.557757591535363245 0.117

Spiegazione

Innanzitutto, nota che Number.call(undefined, N)equivale a Number(N), che ritorna N. Lo useremo più tardi.

Array.apply(null, [undefined, undefined, undefined])è equivalente a Array(undefined, undefined, undefined), che produce un array di tre elementi e assegna undefineda ciascun elemento.

Come puoi generalizzare questo a N elementi? Considera come Array()funziona, che funziona in questo modo:

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;
}

Dal momento che ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)accetta anche un oggetto simile a una matrice tipo duck come secondo parametro. Se invochiamo Array.apply(null, { length: N }), verrà eseguito

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

Ora abbiamo un array N -element, con ogni elemento impostato su undefined. Quando lo chiamiamo .map(callback, thisArg), ogni elemento verrà impostato sul risultato di callback.call(thisArg, element, index, array). Pertanto, [undefined, undefined, …, undefined].map(Number.call, Number)mapperebbe ogni elemento a (Number.call).call(Number, undefined, index, array), che è lo stesso di Number.call(undefined, index, array), che, come abbiamo osservato in precedenza, valuta index. Ciò completa l'array i cui elementi sono uguali al loro indice.

Perché affrontare il problema Array.apply(null, {length: N})invece che solo Array(N)? Dopotutto, entrambe le espressioni risulterebbero in una matrice N- elemento di elementi indefiniti. La differenza è che nella prima espressione ogni elemento è esplicitamente impostato su indefinito, mentre nella seconda ogni elemento non è mai stato impostato. Secondo la documentazione di .map():

callbackviene invocato solo per gli indici dell'array a cui sono stati assegnati valori; non viene invocato per gli indici che sono stati eliminati o ai quali non sono mai stati assegnati valori.

Pertanto, Array(N)è insufficiente; Array(N).map(Number.call, Number)comporterebbe un array inizializzato di lunghezza N .

Compatibilità

Poiché questa tecnica si basa sul comportamento Function.prototype.apply()specificato in ECMAScript 5, non funzionerà nei browser pre-ECMAScript 5 come Chrome 14 e Internet Explorer 9.


62
+1 per intelligenza, ma tieni presente che si tratta di ordini di grandezza PIÙ LENTI di una primitiva per loop: jsperf.com/array-magic-vs-for
warpech

7
Molto intelligente, probabilmente troppo. Sfruttare il fatto che Function.prototype.callil primo parametro è l' thisoggetto da mappare direttamente sul Array.prototype.mapparametro iteratore ha un certo splendore.
Noah Freitas,

14
Questo è davvero molto intelligente (rasenta l'abuso di JS). L'intuizione davvero importante qui è l'idiosincrasia dei mapvalori non assegnati, secondo me. Un'altra versione (e forse leggermente più chiara, anche se più lunga) è: Array.apply(null, { length: N }).map(function(element, index) { return index; })
Ben Reich,

6
@BenReich Ancora meglio (in termini di livelli di abuso di JS): Array.apply(null, new Array(N)).map(function(_,i) { return i; }) o, in caso di es6 e funzioni freccia, ancora più breve: Array.apply(null, new Array(N)).map((_,i) => i)
oddy

1
Se questo restituisce un array che inizia da 1, risponderebbe effettivamente alla domanda dell'OP
Sarsaparilla,

483

Diversi modi con ES6

Utilizzo dell'operatore spread ( ...) e del metodo keys

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

Fill / Mappa

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

Array.from

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

Array.from e { length: N }hack

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

Nota sulla forma generalizzata

Tutte le suddette forme matrici può produrre inizializzate a valori praticamente qualsiasi desiderato modificando i+1l'espressione desiderata (ad esempio i*2, -i, 1+i*2, i%2ed ecc). Se l'espressione può essere espressa da una funzione, fla prima forma diventa semplicemente

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

Esempi:

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

Poiché l'array è inizializzato con undefinedsu ciascuna posizione, il valore di v saràundefined

Esempio che mostra tutti i moduli

Esempio più generico con la funzione di inizializzatore personalizzato, ad fes

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

o anche più semplice

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


33

5
Usa k ++ per le matrici a partire da 0
Borgboy

1
Se vuoi incrementare, non usare k++, usa ++k.
Alex,

4
Attenzione Array.from non è supportato in IE, a meno che non lo si stia riempiendo di poli.
Lauren,

2
Per rendere felice il compilatore TS, considera di sostituire il parametro inutilizzato con lodash: Array.from ({lunghezza: 5}, (_, k) => k + 1);
Journeycorner,

297

Le matrici gestiscono in modo innato le loro lunghezze. Mentre vengono attraversati, i loro indici possono essere conservati in memoria e referenziati a quel punto. Se è necessario conoscere un indice casuale, indexOfè possibile utilizzare il metodo.


Detto questo, per le tue esigenze potresti voler semplicemente dichiarare un array di una certa dimensione:

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

Diffusione

Facendo uso dell'operatore spread ( ...) e del keysmetodo, consente di creare un array temporaneo di dimensioni N per produrre gli indici, quindi un nuovo array che può essere assegnato alla variabile:

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

Fill / Mappa

Puoi prima creare la dimensione dell'array di cui hai bisogno, riempirlo con undefined e quindi creare un nuovo array usando map, che imposta ciascun elemento sull'indice.

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

Array.from

Questo dovrebbe essere inizializzato alla lunghezza della dimensione N e popolare l'array in un passaggio.

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



Al posto dei commenti e della confusione, se si voleva davvero catturare i valori da 1..N negli esempi precedenti, ci sono un paio di opzioni:

  1. se l'indice è disponibile, puoi semplicemente incrementarlo di uno (ad es ++i.).
  2. nei casi in cui l'indice non viene utilizzato - e forse un modo più efficiente - è creare l'array ma fare in modo che N rappresenti N + 1, quindi spostarsi dalla parte anteriore.

    Quindi se desideri 100 numeri:

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





Ritengo che ciò sia utile quando l'array di numeri viene utilizzato per dati che non possono essere elaborati alla fine della ricezione. (Come un modello HTML che sta semplicemente sostituendo i valori.)
Neil Monroe,

Perché qualcuno dovrebbe fare questo è avere una matrice di numeri per popolare un elenco a discesa, dando all'utente una scelta da 1 a 10. Un piccolo array a mano [1,2,3 ... 10] ha senso, ma cosa succede se è da 1 a 50? Cosa succede se il numero finale cambia?
CigarDoug,

@CigarDoug Non dubito che ci sia un caso d'uso, ma suppongo che sia piccolo. Perché sarebbe necessaria una matrice di numeri, di solito quando si scorre su una matrice un indice verrebbe usato come parte del costrutto del ciclo - o come argomento per la funzione del corpo del ciclo, o una variabile contatore - quindi tenere la matrice di numeri sembra banale semplicemente creando un array di larghezza specificata, o solo una variabile che contiene il limite superiore dell'array. Mi vengono in mente alcuni casi d'uso, ma nessuno di questi era stato espresso dall'OP
vol7ron,

4
Come ho detto, ho bisogno di popolare un menu a discesa con i numeri da 1 a 10. Questo è tutto. C'è un caso d'uso, il MIO caso d'uso. È così che ho trovato questa pagina. Quindi, solo costruire un array a mano è stato meno complicato di tutto ciò che ho visto qui. Quindi i miei requisiti non sono i requisiti del PO. Ma ho la mia risposta.
CigarDoug,

1
@ vol7ron C'è un caso d'uso, ne ho anche uno. In angolare, nel paging, voglio mostrare le pagine nel piè di pagina che sono cliccabili. Quindi eseguo il ciclo degli elementi in una vista con * ngFor = "let p of pagesCounter". Hai una soluzione migliore per questo? A proposito, dai un'occhiata a stackoverflow.com/questions/36354325/…
Dalibor

186

In ES6 puoi fare:

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

http://jsbin.com/molabiluwa/edit?js,console

Modifica: modificato Array(45)da Array(N)quando hai aggiornato la domanda.

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


3
+1 perché è un grande O meglio della .join.splitversione cattiva - ma penso ancora che l'umile ciclo sia migliore.
Robin,

Sono d'accordo @Robin - A parte la complessità algoritmica, l'umile loop è sempre più leggibile. Tuttavia, con l'avvento di lambda in Java, penso mapche presto diventerà uno standard per cose come questa.
Nate,

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

8
Non capisco perché .fill()sia necessario. Vedo che lo è quando provo sul sostituto del nodo, ma dal momento Array(1)[0] === undefinedche differenza fa la chiamata a fill () Array(1).fill(undefined)?
Dominic,

11
Per chiunque sia interessato, la differenza tra Array (N) e Array (N) .fill () è spiegata bene qui
Dominic

108

Utilizzare il metodo molto popolare 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); // => []


Eccezionale. Mostrami un grande progetto che comunque non usa il trattino basso ...
Erez Cohen

63
function range(start, end) {
    var foo = [];
    for (var i = start; i <= end; i++) {
        foo.push(i);
    }
    return foo;
}

Quindi chiamato da

var foo = range(1, 5);

Non esiste un modo integrato per farlo in Javascript, ma è una funzione di utilità perfettamente valida da creare se è necessario farlo più di una volta.

Modifica: a mio avviso, la seguente è una funzione di intervallo migliore. Forse solo perché sono influenzato da LINQ, ma penso che sia più utile in più casi. Il tuo chilometraggio può variare.

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;
}

2
Mi piace questo. Se volessi fare il possibile, puoi dichiararlo come Array.prototype.range = function (start, end) {...} ;. Quindi, è possibile chiamare l'intervallo (x, y) su qualsiasi oggetto Array.
Zach Rattner,

8
Piuttosto lo rendono un metodo Arrayinvece Array.prototypeche non c'è motivo (potrebbe anche essere considerato piuttosto stupido) di avere questo metodo su ogni array.
Adamo

9
Array.range(1, 5)sarebbe probabilmente più appropriato, ma c'è qualcosa di interessante nello scrivere [].range(1, 5).
MooGoo,

"Piuttosto trasformalo in un metodo di Array anziché in Array.prototype" - Qual è la differenza? Intendi solo su un array specifico?
pilau,

3
@pilau Come dice Adamo, sembra strano. Se è sul prototipo, puoi dire foo = [1, 2, 3]; bar = foo.range(0, 10);. Ma è solo ... confuso. bar = Array.range(0, 10)è molto più chiaro ed esplicito. L'intervallo non ha nulla a che fare con l'istanza, quindi non c'è motivo di renderla un metodo di istanza.
Ian Henry,

53

il modo più veloce per riempire un Arrayin v8 è:

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

il risultato sarà: [0, 1, 2, 3, 4]


c'è un modo per farlo senza la variabile extra _
bluejayke

@bluejayke no :(
dlex dykyі

duro, sai qual è il codice sorgente di .map? Non sono sicuro che sia più veloce di un ciclo for, ma in caso contrario in teoria possiamo semplicemente definirne la proprietà e crearne una nuova
bluejayke

49

Questa domanda ha molte risposte complicate, ma una semplice riga:

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

Inoltre, sebbene quanto sopra sia breve (e pulito) da scrivere, penso che quanto segue sia un po 'più veloce (per una lunghezza massima di:

127, Int8,

255, Uint8,

32.767, Int16,

65.535, Uint16,

2.147.483.647, Int32,

4.294.967.295, Uint32.

(basato sui valori interi massimi ), eccone di più su Array tipizzati ):

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

Anche se questa soluzione non è altrettanto ideale, perché crea due array e utilizza la dichiarazione di variabile aggiuntiva "$" (non sono sicuro di come aggirare questo metodo con questo metodo). Penso che la seguente soluzione sia il modo più veloce possibile per farlo:

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

Ogni volta che viene fatta questa affermazione, puoi semplicemente usare la variabile "arr" nell'ambito attuale;

Se vuoi farne una semplice funzione (con qualche verifica di base):

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


così, con la funzione sopra, il "one-liner" super-lento sopra diventa il super-veloce, anche più corto:

range(1,14000);

@JVG ma non per la funzione più veloce?
Bluejayke,

Completamente giusto. È questa semplice fodera che tutti cercano!
Sostituisce il

@supersan sebbene sia super lento :)
bluejayke

JavaScript moderno con il nuovo fillmetodo:Array(255).fill(0,0,255)
cacoder

@cacoder quanto è veloce, quante matrici crea e quante iterazioni?
bluejayke,

42

Puoi usare questo:

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

per esempio

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

creerà il seguente array:

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

Inoltre, perché no new Array(10).join().split(',').map(function() {return ++arguments[1]});?
Super

1
@Murplyx per alcuni casi la funzione con argomenti all'interno non sarà ottimizzata dal motore JS (vero anche per V8, vedi jsperf.com/arguments-vs-array-argument/2 )
nktssh

4
Questa è una soluzione interessante ma è del tutto impraticabile: dover analizzare l'array 3 volte (una volta per join, una volta per splite una volta per la cosa che vuoi davvero fare) non è carino - so che sembrano essere caduti in disgrazia per qualche motivo, ma sarebbe molto meglio semplicemente usare un buon vecchio ciclo !
Robin,

42

ES6 questo farà il trucco:

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

controlla il risultato:

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


5
in realtà, hanno chiesto 1..N, non 0..N-1
YakovL

1
sì, [...Array(N + 1).keys()].slice(1)produrrà 1..N
David G

Per qualche motivo questa soluzione non funziona nella versione di produzione dall'app Expo (reagisce nativamente). [...Array(N + 1).keys()]questo codice restituisce un array vuoto, ma solo nella modalità di produzione, usando la modalità di sviluppo funziona.
FabianoLothor,

3
La .keys()risposta è già stata data anni fa e ha ottenuto oltre 500 voti. Cosa aggiunge la tua risposta?
Dan Dascalescu,

39

Se ti capita di usare d3.js nella tua app come sono, D3 offre una funzione di supporto che lo fa per te.

Quindi, per ottenere un array da 0 a 4, è facile come:

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

e per ottenere un array da 1 a 5, come stavi richiedendo:

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

Dai un'occhiata a questo tutorial per maggiori informazioni.


Questo commento mi ha dato l'idea di cercare la funzione range () in RamdaJS, che sembra essere la libreria JS con cui sto lavorando sul mio progetto attuale. Perfetto.
morfico

39

Utilizzo dell'operatore di diffusione ES2015 / ES6

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

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


7
i + 1avrebbe più senso di ++i.
Vincent Cantin,

38

Questo è probabilmente il modo più veloce per generare una matrice di numeri

Più breve

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

In linea

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

Se vuoi iniziare da 1

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]

Vuoi una funzione?

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]

PERCHÉ?

  1. while è il ciclo più veloce

  2. L'impostazione diretta è più veloce di push

  3. [] è più veloce di new Array(10)

  4. è breve ... guarda il primo codice. quindi guarda tutte le altre funzioni qui.

Se ti piace non puoi vivere senza per

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

o

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

8
Sarebbe meglio eseguire il backup di queste affermazioni con parametri di riferimento. Prova jsperf.com .
Matt Ball,

2
lol jsperf ... pls Matt semplicemente allucinante non ti piace la mia risposta fermata downvoting miei altri ... stackoverflow.com/a/18344296/2450730 ... uso console.time () o come si chiama ... NON jsperf .
cocco,

4
Cordiali saluti: Come John Reisig ha pubblicato per la prima volta alcuni anni fa - su alcune piattaforme (che significa windows: P) il tempo viene inviato al browser una volta ogni 16ms. Inoltre, ci sono altri problemi con la misurazione del tempo di esecuzione in ambienti multitasking. jsperf.com ha implementato l'esecuzione dei test in modo che siano statisticamente corretti. Va bene eseguire console.time()per avere un'intuizione, ma per una prova, hai bisogno di jsperf.com E ti mostra i risultati cross-browser di altre persone (hardware diverso ecc.)
naugtur

3
@cocco questo non è corretto:var a=[],b=N;while(b--){a[b]=a+1};
vintagexav

5
@ cocco— mentre non è sempre più veloce di altri loop. In alcuni browser, un ciclo while decrementante è molto più lento di un ciclo for, non puoi fare affermazioni generali sulle prestazioni javascript in quel modo perché ci sono così tante implementazioni con così tante diverse ottimizzazioni. Tuttavia, in generale mi piace il tuo approccio. ;-)
RobG

32

Se stai usando lodash, puoi usare _.range :

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

Crea una serie di numeri (positivi e / o negativi) che avanzano dall'inizio fino alla fine, ma non compresa. Viene utilizzato un passaggio -1 se viene specificato un inizio negativo senza fine o passaggio. Se end non è specificato, è impostato per iniziare con start quindi impostato su 0.

Esempi:

_.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);
// ➜ []

32

il nuovo modo di riempire Arrayè:

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

il risultato sarà: [0, 1, 2, 3, 4]


Questa è una risposta davvero buona, anche se tecnicamente la domanda era di 1-N, non di 0- (N-1)
bluejayke

30

con ES6 puoi fare:

// `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)

Poiché i valori dell'array vengono effettivamente riempiti utilizzando questa soluzione, mape forEachfunzionerà.
dontmentionthebackup del

27

Rapporto di sintesi finale. Drrruummm Rolll -

Questo è il codice più breve per generare un array di dimensioni N (qui 10) senza usare ES6 . La versione di Cocco sopra è vicina ma non la più breve.

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

Ma il vincitore indiscusso di questo codice golf (competizione per risolvere un problema particolare con il minor numero di byte di codice sorgente) è Niko Ruotsalainen . Utilizzo di Array Constructor e ES6 spread operator . (La maggior parte della sintassi ES6 è un tipo di codice valido, ma non lo è il seguente. Quindi sii prudente mentre lo usi)

[...Array(10).keys()]

Perché votare male? Elenco di risposte lunghe difficili da seguire, quindi ho pensato di riassumere.
sapy,

non è questo 0-10? [... Array (10) .keys ()]
Greg

Webstorm suggerisce (nuovo array (10)). Keys (), è giusto?
Guy,

(new Array (10)). keys (), restituisce ArrayIterator {}, non l'array
sapy

Questo crea una variabile globale a. Il ciclo dovrebbe esserefor(var a=[];n--;a[n]=n+1)
kube il

20

Esiste un altro modo in ES6, usando Array.from che accetta 2 argomenti, il primo è un arrayLike (in questo caso un oggetto con lengthproprietà), e il secondo è una funzione di mappatura (in questo caso mappiamo l'elemento sul suo indice)

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

questo è più breve e può essere utilizzato per altre sequenze come la generazione di numeri pari

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

Inoltre, questo ha prestazioni migliori rispetto alla maggior parte degli altri modi perché si sposta in loop una sola volta attraverso l'array. Controlla lo snippit per alcuni confronti

// 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")


Ehi, è pulito, mi piace. Tuttavia, non restituisce i risultati previsti dall'OP. Per fare ciò dovrebbe essere scritto comeArray.from({length:N}, (v,i) => i+1)
CervEd,


16

Utilizzo di nuovi metodi di array e =>sintassi delle funzioni dallo standard ES6 (solo Firefox al momento della scrittura).

Riempiendo i fori con undefined:

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

Array.fromtrasforma i "buchi" in undefinedmodo che Array.mapfunzioni come previsto:

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

7
Allo stesso modo, è possibile anche effettuare le seguenti operazioni in ES6: Array.from({length: N}, (v, k) => k).
XåpplI'-I0llwlg'I -

L'approccio di Xappli è preferito: Array.from è stato creato per quasi questo scenario esatto e implica un callback di mappatura. È un'ottima soluzione al problema generale di voler usare i metodi array su qualcosa di simile a un array, senza ricorrere ad approcci dettagliati come Array.prototype.map.call, ad esempio, per NodeLists da cui è tornato document.querySelectorAll. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Josh di Qaribou,

Sto valutando questo rispetto alla sintassi dell'intervallo di sottolineatura e l'intervallo è migliore.
Ooolala,

Tecnicamente non è ciò Array.fromche trasforma i valori sparsi in indefiniti. Piuttosto Array(5)viene chiamato come un argomento oggetto che a sua volta interpreta i valori sparsi come valori indefiniti :)
CervEd



12

In ES6:

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

ES5:

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

10

Solo un'altra versione ES6 .

Utilizzando il Array.fromsecondo argomento facoltativo:

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

Possiamo costruire l'array numerato dalle Array(10)posizioni vuote :

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

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


Questo è più complicato e ~ 10 volte più lento di [...Array(11).keys()].slice(1).
Dan Dascalescu,

10

Sembra che l'unico sapore attualmente non in questo elenco piuttosto completo di risposte sia quello con un generatore; quindi per porre rimedio a quanto segue:

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

che può essere utilizzato così:

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

La cosa bella di questo è che non devi solo incrementare ... Per trarre ispirazione dalla risposta data da @ igor-shubin, potresti creare una serie di random molto facilmente:

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

E piuttosto che qualcosa di lungo operativamente costoso come:

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

potresti invece fare:

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

10

È possibile utilizzare il riempimento dell'array e la mappa da Es6; proprio come alcune persone hanno suggerito nelle risposte che hanno dato a questa domanda. Di seguito alcuni esempi:

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]

Preferisco questo perché lo trovo semplice e facile.



9

Usando ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);

Grazie! Questa è stata la risposta più elegante secondo me! Si potrebbe anche usare Array.from(Array(n))se l'operatore di diffusione non è supportato.
Amit

All'inizio non sapevo perché dovevi usare l'operatore spread, ma poi ho letto quanto segue mapsu MDN : "Non viene chiamato per gli elementi mancanti dell'array (ovvero gli indici che non sono mai stati impostati, che hanno stato eliminato o a cui non è mai stato assegnato un valore). "
battmanz

9

Object.keys(Array.apply(0, Array(3))).map(Number)

Ritorni [0, 1, 2]. Molto simile alla risposta eccellente di Igor Shubin , ma con un po 'meno inganno (e un personaggio in più).

Spiegazione:

  • Array(3) // [undefined × 3]Genera una matrice di lunghezza n = 3. Purtroppo questo array è quasi inutile per noi, quindi dobbiamo ...
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined]rendere l'array iterabile. Nota: null è più comune come primo arg di apply ma 0 è più breve.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] quindi ottenere le chiavi dell'array (funziona perché le matrici sono l'array typeof è un oggetto con indici per le chiavi.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] e mappare sui tasti, convertendo le stringhe in numeri.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.