Crie uma matriz JavaScript contendo 1… N

Eu estou procurando por quaisquer alternativas para o abaixo para criar um array JavaScript contendo 1 a N, onde N é conhecido apenas em tempo de execução.

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

Para mim, parece que deveria haver uma maneira de fazer isso sem o loop.

Se eu obtiver o que você quer depois, você quer uma matriz de números 1..n que você possa posteriormente percorrer.

Se isso é tudo que você precisa, você pode fazer isso?

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

então quando você quiser usá-lo … (não otimizado, apenas por exemplo)

 for(var i=0;i'); } 

Por exemplo, se você não precisa armazenar nada na matriz, você só precisa de um contêiner do tamanho certo que você pode percorrer … isso pode ser mais fácil.

Veja isso em ação aqui: http://jsfiddle.net/3kcvm/

Você pode fazer isso:

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

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

ou com valores randoms:

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

resultado: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958732, 0.16363654541783035]

Explicação

Primeiro, observe que Number.call(undefined, N) é equivalente a Number(N) , que apenas retorna N Nós vamos usar esse fato mais tarde.

Array.apply(null, [undefined, undefined, undefined]) é equivalente a Array(undefined, undefined, undefined) , que produz uma matriz de três elementos e atribui undefined a cada elemento.

Como você pode generalizar isso para N elementos? Considere como o Array() funciona, o que é algo assim:

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

Como o ECMAScript 5 , Function.prototype.apply(thisArg, argsArray) também aceita um object semelhante a um array tipo pato como seu segundo parâmetro. Se invocarmos Array.apply(null, { length: N }) , então ele será executado

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

Agora temos um array de N- elementos, com cada elemento definido como undefined . Quando chamamos .map(callback, thisArg) , cada elemento será configurado para o resultado de callback.call(thisArg, element, index, array) . Portanto, [undefined, undefined, …, undefined].map(Number.call, Number) cada elemento para (Number.call).call(Number, undefined, index, array) , que é o mesmo que Number.call(undefined, index, array) , que, como observamos anteriormente, avalia para index . Isso completa a matriz cujos elementos são os mesmos que seus índices.

Por que passar pelo problema de Array.apply(null, {length: N}) vez de apenas Array(N) ? Afinal, ambas as expressões resultariam em um array N- element de elementos indefinidos. A diferença é que na expressão anterior, cada elemento é explicitamente definido como indefinido, enquanto no segundo, cada elemento nunca foi definido. De acordo com a documentação do .map() :

callback é chamado apenas para índices da matriz que possui valores atribuídos; ele não é chamado para índices que foram excluídos ou que nunca receberam valores atribuídos.

Portanto, Array(N) é insuficiente; Array(N).map(Number.call, Number) resultaria em uma matriz não inicializada de comprimento N.

Compatibilidade

Como essa técnica depende do comportamento de Function.prototype.apply() especificado no ECMAScript 5, ela não funcionará em navegadores anteriores ao ECMAScript 5, como o Chrome 14 e o Internet Explorer 9.

No ES6 usando os methods Array from () e keys () .

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

Versão mais curta usando o operador de spread .

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

Simples e breve no ES6 :

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

Portanto :

  Array.from({length: N}, (v, k) => k+1); // [1,2,3,...,N] 
 const range = (N) => Array.from({length: N}, (v, k) => k+1) ; console.log( range(5) ) 

No ES6 você pode fazer:

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

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

Edit: Changed Array(45) to Array(N) desde que você atualizou a questão.

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

Use o muito popular método 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); // => [] 

Eu sei que sua pergunta está pedindo para preencher um array numericamente, mas não tenho certeza de por que você gostaria de fazer isso.

Arrays gerenciam inatamente seus comprimentos. À medida que são percorridos, seus índices podem ser mantidos na memory e referenciados nesse ponto. Se um índice random precisar ser conhecido, o método indexOf poderá ser usado.

Dito isto, para as suas necessidades você pode apenas querer declarar um array de um certo tamanho:

 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

Espalhar

Fazendo uso do método de operador de spread ( ... ) e keys , permite que você crie um array temporário de tamanho N para produzir os índices e, em seguida, um novo array que pode ser atribuído à sua variável:

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

Preencher / Mapear

Você pode primeiro criar o tamanho do array que você precisa, preenchê-lo com undefined e, em seguida, criar um novo array usando map , que define cada elemento para o índice.

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

Array.from

Isso deve ser inicializado para o tamanho do tamanho N e preencher o array em uma passagem.

 Array.from({ length: N }, (v, i) => i) 
 function range(start, end) { var foo = []; for (var i = start; i < = end; i++) { foo.push(i); } return foo; } 

Então chamado por

 var foo = range(1, 5); 

Não existe uma maneira integrada de fazer isso em Javascript, mas é uma function de utilitário perfeitamente válida para criar, se você precisar fazer isso mais de uma vez.

Edit: Na minha opinião, o seguinte é uma function melhor intervalo. Talvez só porque sou influenciado pelo LINQ, mas acho que é mais útil em mais casos. Sua milhagem pode variar.

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

Você pode usar isto:

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

por exemplo

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

irá criar seguinte array:

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

Se você estiver usando o d3.js em seu aplicativo como eu, o D3 fornece uma function auxiliar que faz isso para você.

Então, para obter uma matriz de 0 a 4, é tão fácil quanto:

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

e para obter uma matriz de 1 a 5, como você estava solicitando:

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

Confira este tutorial para mais informações.

Esta é a maneira mais rápida de gerar uma matriz de números

Mais curto

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

Na linha

 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 você quer começar de 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] 

Quer uma function?

 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] 

PORQUE?

  1. while é o loop mais rápido

  2. A configuração direta é mais rápida do que push

  3. [] é mais rápido que o new Array(10)

  4. é curto … olha o primeiro código. então olhe para todas as outras funções aqui.

Se você gosta, não pode viver sem por

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

ou

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

nota : apply , map , joinsplit …. srsly ??? isso é muito lento !!!!!! e compatibilidade ???

ES6 isso vai fazer o truque:

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

confira o resultado:

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

Usando o operador de espalhamento ES2015 / ES6

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

Se você estiver usando o lodash, você pode usar o _.range :

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

Cria uma matriz de números (positivos e / ou negativos) que progridem desde o início até, mas não incluindo, fim. Um passo de -1 é usado se um início negativo é especificado sem um fim ou passo. Se end não for especificado, ele será configurado para iniciar com start e, em seguida, será definido como 0.

Exemplos:

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

Relatório final de resumo .. Drrruummm Rolll –

Este é o código mais curto para gerar uma matriz de tamanho N (aqui 10) sem usar o ES6 . A versão de Cocco acima é próxima, mas não a mais curta.

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

Mas o vencedor indiscutível deste Code golf (competição para resolver um problema particular nos menores bytes de código-fonte) é Niko Ruotsalainen . Usando Array Constructor e ES6 spread operator . (A maior parte da syntax do ES6 é um typeScript válido, mas o seguinte não é. Portanto, seja criterioso ao usá-la)

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

Usando novos methods Array e => syntax de function do padrão ES6 (somente Firefox no momento da escrita).

Preenchendo buracos com undefined :

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

Array.from transforma “buracos” em undefined modo que o Array.map funcione como esperado:

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

Existe uma outra maneira no ES6, usando Array.from que leva 2 argumentos, o primeiro é um arrayLike (neste caso, um object com a propriedade length ), e o segundo é uma function de mapeamento (nesse caso, mapeamos o item para seu índice )

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

isso é mais curto e pode ser usado para outras sequências como gerar números pares

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

Além disso, isso tem melhor desempenho do que a maioria das outras maneiras, porque ele só faz o loop uma vez na matriz. Verifique o snippit para algumas comparações

 // open the dev console to see results count = 100000 console.time("from object") for (let i = 0; i i ) } console.timeEnd("from object") console.time("from keys") for (let i =0; i 
 for(var i,a=[i=0];i<10;a[i++]=i); 

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

Tente isto:

 var foo = [1, 2, 3, 4, 5]; 

Se você estiver usando o CoffeeScript , você pode criar um intervalo fazendo:

 var foo = [1..5]; 

Caso contrário, se você estiver usando baunilha JavaScript, você terá que usar um loop se você quiser inicializar uma matriz até um comprimento variável.

Um pouco mais simples que a variante de string:

 // create range by N Array(N).join(0).split(0); // create a range starting with 0 as the value Array(7).join(0).split(0).map(Number.call, Number); // [0, 1, 2, 3, 4, 5, 6] 

Apenas mais uma versão ES6 .

Fazendo uso de Array.from segundo argumento opcional:

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

Podemos construir o array numerado a partir das posições vazias do Array(10) :

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

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

Eu estava procurando por uma solução funcional e acabei com:

 function numbers(min, max) { return Array(max-min+2).join().split(',').map(function(e, i) { return min+i; }); } console.log(numbers(1, 9)); 

Nota: join().split(',') transforma o array esparso em um contíguo.

A seguinte function retorna uma matriz preenchida com números:

 var createArrayOfNumbers = function (n) { return Array.apply(null, new Array(n)).map(function (empty, index) { return index; }); }; 

Observe que uma matriz criada com o construtor de matriz consiste em furos, portanto, ela não pode ser percorrida com funções de matriz, como map. Portanto, usando a function Array.apply .

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

Retorna [0, 1, 2] . Muito semelhante à excelente resposta de Igor Shubin , mas com um pouco menos de truques (e um personagem a mais).

Explicação:

  • Array(3) // [undefined × 3] Gerar uma matriz de comprimento n = 3. Infelizmente esta matriz é quase inútil para nós, então temos que…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined] torna o array iterável. Nota: null é mais comum como primeiro argumento de apply, mas 0 é menor.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] seguida, obter as chaves da matriz (funciona porque Arrays são o array typeof é um object com índices para chaves.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] e mapear sobre as chaves, convertendo strings em números.

Improvisando o acima:

 var range = function (n) { return Array(n).join().split(',').map(function(e, i) { return i; }); } 

Pode-se obter as seguintes opções:

1) Array.init para valorizar v

 var arrayInitTo = function (n,v) { return Array(n).join().split(',').map(function() { return v; }); }; 

2) obtenha um intervalo invertido:

 var rangeRev = function (n) { return Array(n).join().split(',').map(function() { return n--; }); }; 

Eu não vi nenhuma solução baseada em funções recursivas (e nunca escrevi funções recursivas eu mesmo) então aqui está minha tentativa.

Note que array.push (algo) retorna o novo tamanho do array:

 (a=[]).push(a.push(a.push(0))) // a = [0, 1, 2] 

E com uma function recursiva:

 var a = (function f(s,e,a,n){return ((n?n:n=s)>e)?a:f(s,e,a?a:a=[],a.push(n)+s)})(start,end) // eg, start = 1, end = 5 

EDIT: duas outras soluções

 var a = Object.keys(new Int8Array(6)).map(Number).slice(1) 

e

 var a = [] var i=setInterval(function(){a.length===5?clearInterval(i):a.push(a.length+1)}) 
 Array(8).fill(0).map(Number.call, Number) 

Stealing Igors Number.call mas usando fill() para encurtar ligeiramente. Só funciona com ES6 e acima.

Parece que o único sabor que não existe atualmente nessa lista bastante completa de respostas é um que apresenta um gerador; Então, para remediar isso:

 const gen = N => [...(function*(){let i=0;while(i 

que pode ser usado assim:

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

O bom disso é que você não precisa apenas incrementar ... Para se inspirar na resposta dada pelo @ igor-shubin, você poderia criar uma série de randoms com muita facilidade:

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

E ao invés de algo demorado operacionalmente caro como:

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

você poderia fazer:

 const fast = N => [...(function*(){let i=0;while(i++ 

Usando o ES6

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

Você pode usar um gerador de function ou function * expression. Aqui está [ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function ] E uma referência ao link do gerador de funções para [ https://developer.mozilla.org/en- EUA / docs / Web / JavaScript / Referência / Declarações / function ].

let a = 1, b = 10;

function* range(a, b) { for (var i = a; i < = b; ++i) yield i; }

Array.from(range(a, b)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[...range(a, b)] // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]