Como criar uma matriz contendo 1… N

1163

Estou procurando por alternativas ao abaixo para criar uma matriz JavaScript contendo de 1 a N, em que N é conhecido apenas em tempo de execução.

var foo = [];

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

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

Godders
fonte
224
Depois de ler esta página inteira, cheguei à conclusão de que seu próprio loop for simples é o mais simples, mais legível e menos suscetível a erros.
Kokodoko
Se alguém precisar de algo mais avançado, criei uma lib node.js que faz isso para números, letras, intervalos negativos / positivos etc. github.com/jonschlinkert/fill-range . É usado em github.com/jonschlinkert/braces para a expansão cinta e github.com/jonschlinkert/micromatch para padrões glob
jonschlinkert
1
Você deve editar para dizer "Como criar uma matriz de comprimento N" em vez de "... contendo 1 ... N", o último implica que haverá elementos com valores de 1 a N
Steven Landow
7
@StevenLandow Por que OP deve renomear? Ele quer uma matriz com valores 1 ... N?
Andre Elrico 19/11/19
Boa pergunta, bom título, (meio) respostas tolas.
Bitterblue 27/03/19

Respostas:

381

Se eu conseguir o que você procura, você deseja uma matriz de números 1..nque você pode percorrer posteriormente.

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

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

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

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

por exemplo, se você não precisar armazenar nada no array, precisará apenas de um contêiner do comprimento certo para repetir ... isso pode ser mais fácil.

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

scunliffe
fonte
4
impressionado, você conseguiu formular minha pergunta melhor do que eu poderia, você está realmente correto, pois, refletindo, tudo o que preciso é de uma série de números que eu possa percorrer mais tarde :) Obrigado pela sua resposta.
Godders 19/09/10
147
@ Gods: Se é isso que você está procurando, por que você precisa de uma matriz? Um simples var n = 45;e, em seguida, loop de 1..nfaria.
casablanca
3
@ Godods - Para observar, se você quiser diminuir o tamanho da matriz depois de criada para o comprimento M, basta usar foo.length = M--- As informações de corte são perdidas. Veja-o em ação ==> jsfiddle.net/ACMXp
Peter Ajtai
24
Eu realmente não entendo por que essa resposta tem votos positivos ... especialmente quando o OP concorda que isso não faz sentido nos comentários acima, já que ele poderia ter feito var n = 45;.
precisa saber é
72
@ scunliffe: Observe que new Array(45);isso não "cria uma matriz de 45 elementos" (no mesmo significado que [undefined,undefined,..undefined]faz). Em vez disso, "cria uma matriz vazia com comprimento = 45" ( [undefined x 45]), o mesmo que var foo = []; foo.length=45;. É por isso forEach, e mapnão se aplica neste caso.
tomalec
1310

No ES6, usando os métodos 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 spread .

[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Niko Ruotsalainen
fonte
75
Apenas uma observação, isso sempre começará em 0. Será necessário encadear mapa à matriz para ajustar os valores ( [...Array(10).keys()].map(x => x++);) para começar em 1
Sterling Archer
32
Mudança apenas map(x => x++)para map(x => ++x)devido ao incremento de precedência acontece após o retorno valor :)
Brock
93
Er o quê !? Por que mapquando você pode simplesmente slice? [...Array(N+1).keys()].slice(1)
24416 Robin
19
Ou não use keyse apenas 1 mapa ->Array.from(Array(10)).map((e,i)=>i+1)
yonatanmn
60
Ou não usar chaves e mapa e apenas passar uma função de mapeamento parafrom Array.from(Array(10), (e,i)=>i+1)
Fabio Antunes
844

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 aleatórios:

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

resultado: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.865384814329494, 0,008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.55775759159369

Explicação

Primeiro, observe que Number.call(undefined, N)é equivalente a Number(N), que apenas retorna N. Nós usaremos 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 undefineda cada elemento.

Como você pode generalizar isso para N elementos? Considere como Array()funciona, que é mais ou menos 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;
}

Desde o ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)também aceita um objeto semelhante a uma matriz do tipo pato como seu segundo parâmetro. Se invocarmos Array.apply(null, { length: N }), ele executará

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

Agora temos uma matriz de elementos N , com cada elemento definido como undefined. Quando o chamamos .map(callback, thisArg), cada elemento será definido como o resultado de callback.call(thisArg, element, index, array). Portanto, [undefined, undefined, …, undefined].map(Number.call, Number)mapearia cada elemento para (Number.call).call(Number, undefined, index, array), que é o mesmo Number.call(undefined, index, array)que, como observamos anteriormente, avalia como index. Isso completa a matriz cujos elementos são iguais ao seu índice.

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

callbacké invocado apenas para índices da matriz que atribuíram valores; não é chamado para índices que foram excluídos ou aos quais nunca foram atribuídos valores.

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

Igor Shubin
fonte
62
+1 para a inteligência, mas por favor note que este é ordens de magnitude mais lento do que um primitivo para loop: jsperf.com/array-magic-vs-for
warpech
7
Muito esperto - provavelmente também. Explorar o fato de que Function.prototype.callo primeiro parâmetro é o thisobjeto para mapear diretamente sobre Array.prototype.mapo parâmetro iterador tem um certo brilho.
Noah Freitas
14
Isso é muito, muito inteligente (beira do abuso de JS). O insight realmente importante aqui é a idiossincrasia de mapvalores não atribuídos, na minha opinião. Outra versão (e possivelmente um pouco mais clara, embora mais longa) é: Array.apply(null, { length: N }).map(function(element, index) { return index; })
Ben Reich
6
@BenReich Ainda melhor (em termos de níveis de abuso de JS): Array.apply(null, new Array(N)).map(function(_,i) { return i; }) ou, no caso das funções es6 e arrow, ainda mais curtos: Array.apply(null, new Array(N)).map((_,i) => i)
oddy
1
Se isso retorna uma matriz que começa em 1, na verdade, ele responderia à pergunta do OP
Sarsaparilla
483

Várias maneiras de usar o ES6

Usando o operador spread ( ...) e o método de chaves

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

Preenchimento / Mapa

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 sobre a forma generalizada

Todas as formas acima pode produzir matrizes inicializados para valores praticamente qualquer pretendidas mudando i+1a expressão necessário (por exemplo i*2, -i, 1+i*2, i%2e etc). Se a expressão puder ser expressa por alguma função f, a primeira forma se tornará simplesmente

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

Exemplos:

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

Como a matriz é inicializada undefinedem cada posição, o valor de v seráundefined

Exemplo mostrando todos os formulários

Exemplo mais genérico com a função inicializadora personalizada, fisto é,

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

ou ainda mais simples

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

Abdennour TOUMI
fonte
33
Melhor resposta IMHO. Veja também developer.mozilla.org/de/docs/Web/JavaScript/Reference/…
le_m
5
Use o k ++ para matrizes que começam em 0
Borgboy 15/03
1
Se você deseja incrementar, não use k++, use ++k.
1328 Alex
4
Cuidado com o Array.from não é suportado no IE, a menos que você esteja preenchendo com poli.
Lauren
2
Para deixar o compilador TS feliz, considere substituir o parâmetro não utilizado por lodash: Array.from ({length: 5}, (_, k) => k + 1);
Journeycorner
297

Matrizes gerenciam in natura seus comprimentos. À medida que são percorridos, seus índices podem ser mantidos na memória e referenciados nesse ponto. Se um índice aleatório precisar ser conhecido, o indexOfmétodo poderá ser usado.


Dito isto, para suas necessidades, você pode apenas querer declarar uma matriz de um determinado 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

Propagação

O uso do operador spread ( ...) e do keysmétodo permite criar uma matriz temporária de tamanho N para produzir os índices e, em seguida, uma nova matriz que pode ser atribuída à sua variável:

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

Preenchimento / Mapa

Você pode primeiro criar o tamanho da matriz de que precisa, preenchê-la com indefinida e criar uma nova matriz usando map, que define cada elemento para o índice.

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

Array.from

Isso deve estar inicializando no tamanho N e preenchendo a matriz em uma passagem.

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



No lugar dos comentários e da confusão, se você realmente deseja capturar os valores de 1..N nos exemplos acima, existem algumas opções:

  1. se o índice estiver disponível, você pode simplesmente incrementá-lo em um (por exemplo, ++i).
  2. nos casos em que o índice não é usado - e possivelmente uma maneira mais eficiente - é criar sua matriz, mas fazer N representar N + 1 e, em seguida, sair da frente.

    Então, se você deseja 100 números:

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




vol7ron
fonte
Eu acredito que isso é útil quando a matriz de números está sendo usada para dados que não podem ser processados ​​no final do recebimento. (Como um modelo HTML que está apenas substituindo valores.)
Neil Monroe
Por que alguém faria isso é ter uma matriz de números para preencher uma lista suspensa, oferecendo ao usuário uma escolha de 1 a 10. Uma matriz pequena à mão [1,2,3 ... 10] faz sentido, mas e se é de 1 a 50? E se o número final mudar?
23418 CigarDoug
@CigarDoug Não duvido que exista um caso de uso, mas meu palpite é pequeno. Por que uma matriz de números seria necessária, geralmente ao iterar sobre uma matriz, um índice seria usado como parte da construção do loop - como um argumento para a função do corpo do loop ou como uma variável contrária -, portanto, manter a matriz dos números parece trivial apenas criando uma matriz de largura especificada ou apenas uma variável que mantém o limite superior da matriz. Eu posso pensar de alguns casos de uso, mas nenhum deles tinha sido expressa pelo OP
vol7ron
4
Como eu disse, preciso preencher um menu suspenso com os números de 1 a 10. Isso é tudo. Há um caso de uso, MEU caso de usuário. Foi assim que encontrei esta página. Portanto, apenas construir uma matriz manualmente era menos complicado do que qualquer coisa que eu vi aqui. Portanto, meus requisitos não são os requisitos do OP. Mas eu tenho minha resposta.
CigarDoug 24/10/19
1
@ vol7ron Existe um caso de uso, eu também tenho um. Em angular, em paginação, quero mostrar as páginas no rodapé que são clicáveis. Então, faço um loop dos elementos em uma exibição com * ngFor = "let p of pagesCounter". Você tem uma solução melhor para isso? Entre em contato com stackoverflow.com/questions/36354325/…
Dalibor
186

No ES6, você pode fazer:

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

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

Editar: alterado Array(45)para Array(N)desde que você atualizou a pergunta.

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

Nate
fonte
3
+1 porque é um todo grande O melhor que o desagradável .join.splitversão - mas eu ainda acho que o loop humilde é melhor.
24416 Robin
Concordo @Robin - Complexidade algorítmica à parte, o loop humilde é sempre mais legível. No entanto, com o advento das lambdas em Java, acho mapque em breve se tornará um padrão para coisas como esta.
Nate
4
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
24616 Robin
8
Não entendo por que .fill()é necessário. Vejo que é quando toco na repl do nó, mas desde Array(1)[0] === undefinedque diferença faz a chamada para preencher () Array(1).fill(undefined)?
Dominic
11
Para qualquer outra pessoa que esteja interessada, a diferença entre Array (N) e Array (N) .Reabastecer () é explicado bem aqui
Dominic
108

Use o método Underscore _.range muito popular

// _.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
fonte
Impressionante. Mostre-me um projeto grande que não use sublinhado de qualquer maneira ...
Erez Cohen
63
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 função 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 função de faixa melhor. Talvez apenas 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;
}
Ian Henry
fonte
2
Eu gosto disso. Se você quiser ir além, poderá declará-lo como Array.prototype.range = function (start, end) {...} ;. Em seguida, você pode chamar o intervalo (x, y) em qualquer objeto Array.
Zach Rattner
8
Em vez disso, torne-o um método, em Arrayvez de Array.prototypenão haver motivo (pode até ser considerado um tanto estúpido) ter esse método em todas as matrizes.
adamse 19/09/10
9
Array.range(1, 5)provavelmente seria mais apropriado, mas há algo legal na escrita [].range(1, 5).
MooGoo 19/09/10
"Em vez disso, torne-o um método de matriz em vez de matriz.protótipo" - Qual é a diferença? Você quer dizer apenas em uma matriz específica?
Pilau #
3
@pilau Assim como diz Adam, parece estranho. Se estiver no protótipo, você pode dizer foo = [1, 2, 3]; bar = foo.range(0, 10);. Mas isso é apenas ... confuso. bar = Array.range(0, 10)é muito mais claro e explícito. O intervalo não tem nada a ver com a instância, portanto não há razão para torná-lo um método de instância.
11113 Ian Henry
53

a maneira mais rápida de preencher uma Arrayv8 é:

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

O resultado será: [0, 1, 2, 3, 4]

Alex Dykyі
fonte
há uma maneira de fazê-lo sem a variável adicional _
bluejayke
@bluejayke no :(
аlex dykyі
áspero, você sabe qual é o código fonte do .map? Eu não tenho certeza se o seu mais rápido do que um loop for, mas se não, então, teoricamente, podemos apenas defineProperty e fazer um novo
bluejayke
49

Esta pergunta tem muitas respostas complicadas, mas uma única linha:

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

Além disso, embora o texto acima seja curto (e arrumado) para escrever, acho que o seguinte é um pouco mais rápido (para um comprimento máximo de:

127, Int8,

255, Uint8,

32.767, Int16,

65.535, Uint16,

2.147.483.647, Int32,

4.294.967.295, Uint32.

(com base nos valores máximos de números inteiros ), veja também mais sobre matrizes digitadas ):

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

Embora essa solução também não seja tão ideal, ela cria duas matrizes e usa a declaração de variável extra "$" (não há nenhuma maneira de contornar isso usando esse método). Eu acho que a solução a seguir é a maneira mais rápida possível de fazer isso:

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

A qualquer momento após a declaração, você pode simplesmente usar a variável "arr" no escopo atual;

Se você deseja criar uma função simples (com algumas verificações básicas):

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


portanto, com a função acima, o super lento "single-liner" acima torna-se super-rápido e ainda mais curto:

range(1,14000);
bluejayke
fonte
@JVG, mas não para a função mais rápida?
22419 bluejayke
Exatamente certo. É este forro simples que todo mundo procura!
supersan
@supersan embora sua super lento :)
bluejayke
Javascript moderno com o novo fillmétodo:Array(255).fill(0,0,255)
cacoder
@ codificador Quão rápido é, quantas matrizes ele cria e quantas iterações?
bluejayke
42

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

criará a seguinte matriz:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nktssh
fonte
Além disso, por que não new Array(10).join().split(',').map(function() {return ++arguments[1]});?
Super
1
@Murplyx para alguns casos funcionar com argumentos dentro não será otimizado pelo motor de JS (verdade mesmo para V8, consulte jsperf.com/arguments-vs-array-argument/2 )
nktssh
4
Essa é uma solução interessante, mas é totalmente impraticável - ter que analisar o array três vezes (uma vez join, uma splitvez e uma vez para o que você realmente quer fazer) não é bom - eu sei que eles parecem ter caído em desuso por alguma razão, mas seria muito melhor simplesmente usar um bom loop antiquado !
24416 Robin
42

ES6, isso fará o truque:

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

confira o resultado:

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

cristão
fonte
5
na verdade, eles pediram 1..N, não 0..N-1 #
YakovL
1
sim, [...Array(N + 1).keys()].slice(1)vai render 1..N
David G
Por algum motivo, esta solução não funciona no aplicativo Version de produção da Expo (nativo de reação). [...Array(N + 1).keys()]esse código retorna uma matriz vazia, mas apenas no modo de produção, usando o modo de desenvolvimento funciona.
precisa saber é o seguinte
3
A .keys()resposta já foi dada anos atrás e tem mais de 500 votos. O que sua resposta adiciona a ela?
Dan Dascalescu 13/09/18
39

Se você estiver usando o d3.js no seu aplicativo como eu, o D3 fornece uma função auxiliar que faz isso por você.

Portanto, 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, conforme solicitado:

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

Confira este tutorial para mais informações.

Tyler Rick
fonte
Esse comentário me deu a idéia de procurar a função range () no RamdaJS, que é a biblioteca JS com a qual estou trabalhando no meu projeto atual. Perfeito.
morphatic
39

Usando o operador de expansão ES2015 / ES6

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

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

Vlad Bezden
fonte
7
i + 1faria mais sentido do que ++i.
Vincent Cantin
38

Esta é provavelmente 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ê deseja 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 função?

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 que push

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

  4. é curto ... olha o primeiro código. então veja 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]
cocco
fonte
8
Seria melhor fazer backup dessas reivindicações com referências. Tente jsperf.com .
Matt Bola
2
lol jsperf ... pls Matt apenas porque você não gosta da minha resposta pare de votar abaixo dos outros ... stackoverflow.com/a/18344296/2450730 ... use console.time () ou como é chamado ... NÃO jsperf .
cocco 21/08/13
4
FYI: Como John Reisig publicou pela primeira vez há alguns anos - em algumas plataformas (o que significa janelas: P), o tempo está sendo alimentado no navegador uma vez a cada 16ms. Também existem outros problemas com a medição do tempo de execução em ambientes multitarefa. O jsperf.com implementou a execução dos testes para que eles sejam estatisticamente corretos. É ok para ser executado console.time()para obter uma intuição, mas para uma prova, você precisa jsperf.com e mostra-lhe cross-browser resultados de outras pessoas (hardware diferentes, etc.)
naugtur
3
@cocco isso está incorreto:var a=[],b=N;while(b--){a[b]=a+1};
vintagexav
5
@ cocco - embora nem sempre seja mais rápido que outros loops. Em alguns navegadores, um loop decrementar while é muito mais lento que um loop for, não é possível fazer declarações gerais sobre o desempenho do javascript dessa maneira, porque existem muitas implementações com tantas otimizações diferentes. No entanto, em geral, eu gosto da sua abordagem. ;-)
RobG
32

Se você estiver usando lodash, poderá usar _.range :

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

Cria uma matriz de números (positivos e / ou negativos) que progridem do início até o final, mas não incluem. Uma etapa de -1 é usada se uma partida negativa for especificada sem um fim ou etapa. Se end não for especificado, ele será configurado para iniciar com start e, em seguida, 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);
// ➜ []
Hongbo Miao
fonte
32

a nova maneira de preencher Arrayé:

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

O resultado será: [0, 1, 2, 3, 4]

Alex Dykyі
fonte
Esta é uma resposta muito boa, embora tecnicamente a pergunta fosse de 1-N, não 0- (N-1)
bluejayke
30

com o ES6, você pode fazer:

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

fonte
Como os valores da matriz são realmente preenchidos usando esta solução mape forEachfuncionarão.
dontmentionthebackup
27

Relatório Resumo Final. 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 código de golfe (competição para resolver um problema específico com o menor número de bytes de código-fonte) é Niko Ruotsalainen . Usando o Array Constructor e o operador de propagação ES6 . (A maioria da sintaxe do ES6 é typeScript válida, mas a seguir não é. Portanto, seja criterioso ao usá-lo)

[...Array(10).keys()]
sapy
fonte
Por que votar abaixo? Lista longa de respostas difícil de seguir, por isso pensei em resumir.
S28 de
não é 0-10? [... Matriz (10) .keys ()]
Greg
A tempestade na Web sugere (nova matriz (10)). Keys (), está certo?
15136 Guy
(new Array (10)) teclas (), retorna ArrayIterator {}, e não a matriz.
sapy
Isso cria uma variável global a. O circuito deve serfor(var a=[];n--;a[n]=n+1)
kube
20

Existe uma outra maneira no ES6, usando Array.from, que recebe 2 argumentos, o primeiro é um arrayLike (neste caso, um objeto com lengthpropriedade) e o segundo é uma função 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 seqüências, como gerar números pares

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

Além disso, ele tem um desempenho melhor do que a maioria das outras maneiras, porque faz um loop apenas 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<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
fonte
Ei, isso é legal, eu gosto. No entanto, ele não retorna os resultados esperados pelo OP. Para fazer isso, seria necessário escrever como #Array.from({length:N}, (v,i) => i+1)
CervEd 22/10
Esses hacks neato ainda são 5 a 10 vezes mais lentos do que um bom e velho loop .
Dan Dascalescu 13/09/18
16

Usando novos métodos Array e =>sintaxe da função do padrão ES6 (somente Firefox no momento da redação).

Preenchendo orifícios com undefined:

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

Array.fromtransforma "buracos" em undefinedassim Array.mapfunciona como esperado:

Array.from(Array(5)).map((_, i) => i + 1)
szymzet
fonte
7
Da mesma forma, você também pode fazer o seguinte em ES6: Array.from({length: N}, (v, k) => k).
XåpplI'-I0llwlg'I -
A abordagem do Xappli é preferida: Array.from foi criado para quase esse cenário exato e implica um retorno de chamada de mapeamento. É uma excelente solução para o problema geral de querer usar métodos Array em algo parecido com array, sem recorrer a abordagens detalhadas como Array.prototype.map.call, por exemplo, para NodeLists retornadas document.querySelectorAll. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Josh de Qaribou
Estou avaliando isso contra a sintaxe do intervalo de sublinhado e o intervalo é melhor.
Ooolala 6/11
Tecnicamente, não é isso Array.fromque transforma os valores esparsos em indefinidos. Em vez Array(5)é chamado como um objeto argumentos que por sua vez interpreta os valores esparsos como valores indefinidos :)
Cerved
15

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

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

Alex Dykyі
fonte
Agradável! Também posso escrever isso de forma mais sucinta como[...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
fonte
Realmente fantástico! Tx!
Pedro Ferreira
12

No ES6:

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

ES5:

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

Apenas outra versão do ES6 .

Usando o Array.fromsegundo argumento opcional:

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

Podemos construir a matriz numerada a partir das Array(10)posições vazias :

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

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

zurfyx
fonte
Isso é mais complicado e ~ 10x mais lento que [...Array(11).keys()].slice(1).
Dan Dascalescu 13/09/18
10

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

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

que pode ser usado assim:

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

O bom disso é que você não precisa incrementar ... Para se inspirar na resposta que a igor-shubin deu, você pode criar uma variedade de randoms com muita facilidade:

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

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++<N)yield i*5})()]
Robin
fonte
10

Você pode usar o preenchimento da matriz e o mapa do Es6; assim como algumas pessoas sugeriram nas respostas que deram para esta pergunta. Abaixo estão alguns exemplos:

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]

Prefiro isso porque acho mais direto e fácil.

Gbemi Kadri
fonte
9

Usando o ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);
Geoffrey Abdallah
fonte
Obrigado! Esta foi a resposta mais elegante na minha opinião! Pode-se também usar Array.from(Array(n))se o operador de propagação não for suportado.
Amit
No começo, eu não sabia por que você tinha que usar o operador spread, mas depois li o seguinte sobre o mapMDN : "Não é necessário elementos ausentes da matriz (ou seja, índices que nunca foram definidos, que foram foram excluídos ou aos quais nunca foi atribuído um valor) ".
battmanz
9

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 truque (e um personagem a mais).

Explicação:

  • Array(3) // [undefined × 3]Gere uma matriz de comprimento n = 3. Infelizmente, essa matriz é quase inútil para nós, então temos que…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined]torne a matriz iterável. Nota: null é mais comum que o primeiro argumento da aplicação, mas 0 é menor.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] em seguida, obtenha as chaves da matriz (funciona porque Matrizes são o tipo de matriz é um objeto com índices para chaves.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] e mapeie as teclas, convertendo cadeias em números.
mLuby
fonte