O JavaScript tem um método como “range ()” para gerar um intervalo dentro dos limites fornecidos?

No PHP, você pode fazer …

range(1, 3); // Array(1, 2, 3) range("A", "C"); // Array("A", "B", "C") 

Ou seja, existe uma function que permite obter um intervalo de números ou caracteres passando os limites superior e inferior.

Existe alguma coisa embutida no JavaScript nativamente para isso? Se não, como eu implementaria isso?

Números

 [...Array(5).keys()]; => [0, 1, 2, 3, 4] 

Iteração personagem

 String.fromCharCode(...[...Array('D'.charCodeAt(0) - 'A'.charCodeAt(0) + 1).keys()].map(i => i + 'A'.charCodeAt(0))); => "ABCD" 

Como funções

 function range(size, startAt = 0) { return [...Array(size).keys()].map(i => i + startAt); } function characterRange(startChar, endChar) { return String.fromCharCode(...range(endChar.charCodeAt(0) - startChar.charCodeAt(0), startChar.charCodeAt(0))) } 

Como funções digitadas

 function range(size:number, startAt:number = 0):ReadonlyArray { return [...Array(size).keys()].map(i => i + startAt); } function characterRange(startChar:string, endChar:string):ReadonlyArray { return String.fromCharCode(...range(endChar.charCodeAt(0) - startChar.charCodeAt(0), startChar.charCodeAt(0))) } 

lodash.js function _.range()

 _.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] String.fromCharCode(..._.range('A'.charCodeAt(0), 'D'.charCodeAt(0) + 1)); => "ABCD" 

Navegadores não es6 antigos sem biblioteca:

 Array.apply(null, Array(5)).map(function (_, i) {return i;}); => [0, 1, 2, 3, 4] 
 console.log([...Array(5).keys()]); 

Para números, você pode usar o ES6 Array.from() , que funciona em tudo atualmente, exceto no IE:

Versão mais curta:

 Array.from({length: 20}, (x,i) => i); 

Versão mais longa:

 Array.from(new Array(20), (x,i) => i) 

que cria uma matriz de 0 a 19 inclusive. Isso pode ser ainda mais reduzido para uma dessas formas:

 Array.from(Array(20).keys()) // or [...Array(20).keys()] 

Os limites inferior e superior também podem ser especificados, por exemplo:

 Array.from(new Array(20), (x,i) => i + *lowerBound*) 

Um artigo descrevendo isso com mais detalhes: http://www.2ality.com/2014/05/es6-array-methods.html

Aqui estão meus 2 centavos:

  function range(start, count) { return Array.apply(0, Array(count)) .map(function (element, index) { return index + start; }); } 

Ele funciona para caracteres e números, indo para frente ou para trás com uma etapa opcional.

 var range = function(start, end, step) { var range = []; var typeofStart = typeof start; var typeofEnd = typeof end; if (step === 0) { throw TypeError("Step cannot be zero."); } if (typeofStart == "undefined" || typeofEnd == "undefined") { throw TypeError("Must pass start and end arguments."); } else if (typeofStart != typeofEnd) { throw TypeError("Start and end arguments must be of same type."); } typeof step == "undefined" && (step = 1); if (end < start) { step = -step; } if (typeofStart == "number") { while (step > 0 ? end >= start : end < = start) { range.push(start); start += step; } } else if (typeofStart == "string") { if (start.length != 1 || end.length != 1) { throw TypeError("Only strings with one character are supported."); } start = start.charCodeAt(0); end = end.charCodeAt(0); while (step > 0 ? end >= start : end < = start) { range.push(String.fromCharCode(start)); start += step; } } else { throw TypeError("Only string and number types are supported"); } return range; } 

jsFiddle .

Se aumentar os tipos nativos é sua coisa, então atribua-o a Array.range .

 var range = function(start, end, step) { var range = []; var typeofStart = typeof start; var typeofEnd = typeof end; if (step === 0) { throw TypeError("Step cannot be zero."); } if (typeofStart == "undefined" || typeofEnd == "undefined") { throw TypeError("Must pass start and end arguments."); } else if (typeofStart != typeofEnd) { throw TypeError("Start and end arguments must be of same type."); } typeof step == "undefined" && (step = 1); if (end < start) { step = -step; } if (typeofStart == "number") { while (step > 0 ? end >= start : end < = start) { range.push(start); start += step; } } else if (typeofStart == "string") { if (start.length != 1 || end.length != 1) { throw TypeError("Only strings with one character are supported."); } start = start.charCodeAt(0); end = end.charCodeAt(0); while (step > 0 ? end >= start : end < = start) { range.push(String.fromCharCode(start)); start += step; } } else { throw TypeError("Only string and number types are supported"); } return range; } console.log(range("A", "Z", 1)); console.log(range("Z", "A", 1)); console.log(range("A", "Z", 3)); console.log(range(0, 25, 1)); console.log(range(0, 25, 5)); console.log(range(20, 5, 5)); 

Minha nova forma favorita ( ES2015 )

 Array(10).fill(1).map((x, y) => x + y) 

E se você precisar de uma function com um parâmetro de step :

 const range = (start, stop, step = 1) => Array(Math.ceil((stop - start) / step)) .fill(start) .map((x, y) => x + y * step) 
 Array.range= function(a, b, step){ var A= []; if(typeof a== 'number'){ A[0]= a; step= step || 1; while(a+step< = b){ A[A.length]= a+= step; } } else{ var s= 'abcdefghijklmnopqrstuvwxyz'; if(a=== a.toUpperCase()){ b=b.toUpperCase(); s= s.toUpperCase(); } s= s.substring(s.indexOf(a), s.indexOf(b)+ 1); A= s.split(''); } return A; } Array.range(0,10); // [0,1,2,3,4,5,6,7,8,9,10] Array.range(-100,100,20); // [-100,-80,-60,-40,-20,0,20,40,60,80,100] Array.range('A','F'); // ['A','B','C','D','E','F') Array.range('m','r'); // ['m','n','o','p','q','r'] 

OK, em JavaScript não temos uma function range() como PHP , então precisamos criar a function que é bem fácil, eu escrevo par de funções de uma linha para você e separo-as para Numbers e Alphabets como abaixo:

para números :

 function numberRange (start, end) { return new Array(end - start).fill().map((d, i) => i + start); } 

e chame assim:

 numberRange(5, 10); //[5, 6, 7, 8, 9] 

para alfabetos :

 function alphabetRange (start, end) { return new Array(end.charCodeAt(0) - start.charCodeAt(0)).fill().map((d, i) => String.fromCharCode(i + start.charCodeAt(0))); } 

e chame assim:

 alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"] 

function de faixa simples:

 function range(start, stop, step){ var a=[start], b=start; while(b 
 var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l); 

Função útil para fazer o truque, execute o trecho de código abaixo

 function range(start, end, step, offset) { var len = (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1; var direction = start < end ? 1 : -1; var startingPoint = start - (direction * (offset || 0)); var stepSize = direction * (step || 1); return Array(len).fill(0).map(function(_, index) { return startingPoint + (stepSize * index); }); } console.log('range(1, 5)=> ' + range(1, 5)); console.log('range(5, 1)=> ' + range(5, 1)); console.log('range(5, 5)=> ' + range(5, 5)); console.log('range(-5, 5)=> ' + range(-5, 5)); console.log('range(-10, 5, 5)=> ' + range(-10, 5, 5)); console.log('range(1, 5, 1, 2)=> ' + range(1, 5, 1, 2)); 

O JavaScript padrão não possui uma function interna para gerar intervalos. Várias estruturas javascript adicionam suporte para esses resources, ou, como outros apontaram, você pode sempre criar o seu próprio.

Se você quiser verificar novamente, o recurso definitivo é o padrão ECMA-262 .

Usando o operador de distribuição Harmony e as funções de seta:

 var range = (start, end) => [...Array(end - start + 1)].map((_, i) => start + i); 

Exemplo:

 range(10, 15); [ 10, 11, 12, 13, 14, 15 ] 

Fiz algumas pesquisas sobre algumas diversas funções do Range. Verifica a comparação jsperf das diferentes maneiras de fazer essas funções. Certamente não é uma lista perfeita ou exaustiva, mas deve ajudar 🙂

O vencedor é…

 function range(lowEnd,highEnd){ var arr = [], c = highEnd - lowEnd + 1; while ( c-- ) { arr[c] = highEnd-- } return arr; } range(0,31); 

Tecnicamente não é o mais rápido no firefox, mas a diferença de velocidade louca (imho) no cromo compensa isso.

Também é interessante observar o quanto o cromo é mais rápido com essas funções de array do que o firefox. O Chrome é pelo menos 4 ou 5 vezes mais rápido .

Um desafio interessante seria escrever a function mais curta para fazer isso. Recursão ao resgate!

 function r(a,b){return a>b?[]:[a].concat(r(++a,b))} 

Tende a ser lento em grandes intervalos, mas felizmente computadores quânticos estão ao virar da esquina.

Um bônus adicional é que é ofuscante. Porque todos nós sabemos o quanto é importante esconder nosso código de olhares indiscretos.

Para realmente ofuscar a function, faça isso:

 function r(a,b){return (ab?[]:[a]).sort(function(a,b){return ab})} 

Eu codificaria algo assim:

 function range(start, end) { return Array(end-start).join(0).split(0).map(function(val, id) {return id+start}); } range(-4,2); // [-4,-3,-2,-1,0,1] range(3,9); // [3,4,5,6,7,8] 

Ele se comporta de maneira semelhante ao intervalo do Python:

 >>> range(-4,2) [-4, -3, -2, -1, 0, 1] 

Você pode usar o intervalo lodash ou Undescore.js :

 var range = require('lodash/range') range(10) // -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] 

Alternativamente, se você precisa apenas de um intervalo consecutivo de números inteiros, você pode fazer algo como:

 Array.apply(undefined, { length: 10 }).map(Number.call, Number) // -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] 

Na range ES6 pode ser implementado com geradores :

 function* range(start=0, end=null, step=1) { if (end == null) { end = start; start = 0; } for (let i=start; i < end; i+=step) { yield i; } } 

Essa implementação salva a memory ao iterar sequências grandes, porque não precisa materializar todos os valores em uma matriz:

 for (let i of range(1, oneZillion)) { console.log(i); } 

Uma implementação bastante minimalista que emprega fortemente o ES6 pode ser criada da seguinte maneira, chamando a atenção para o método estático Array.from() :

 const getRange = (start, stop) => Array.from( new Array((stop - start) + 1), (_, i) => i + start ); 

Outra versão usando geradores ES6 (veja grande resposta de Paolo Moretti com geradores ES6 ):

 const RANGE = (a,b) => Array.from((function*(x,y){ while (x < = y) yield x++; })(a,b)); console.log(RANGE(3,7)); // [ 3, 4, 5, 6, 7 ] 

Ou, se precisarmos apenas de iteráveis, então:

 const RANGE_ITER = (a,b) => (function*(x,y){ while (x++< y) yield x; })(a,b); for (let n of RANGE_ITER(3,7)){ console.log(n); } 

Embora isso não seja do PHP , mas sim uma imitação do range do Python .

 function range(start, end) { var total = []; if (!end) { end = start; start = 0; } for (var i = start; i < end; i += 1) { total.push(i); } return total; } console.log(range(10)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] console.log(range(0, 10)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] console.log(range(5, 10)); // [5, 6, 7, 8, 9] 

Usando geradores Harmony , suportados por todos os navegadores, exceto o IE11 :

 var take = function (amount, generator) { var a = []; try { while (amount) { a.push(generator.next()); amount -= 1; } } catch (e) {} return a; }; var takeAll = function (gen) { var a = [], x; try { do { x = a.push(gen.next()); } while (x); } catch (e) {} return a; }; var range = (function (d) { var unlimited = (typeof d.to === "undefined"); if (typeof d.from === "undefined") { d.from = 0; } if (typeof d.step === "undefined") { if (unlimited) { d.step = 1; } } else { if (typeof d.from !== "string") { if (d.from < d.to) { d.step = 1; } else { d.step = -1; } } else { if (d.from.charCodeAt(0) < d.to.charCodeAt(0)) { d.step = 1; } else { d.step = -1; } } } if (typeof d.from === "string") { for (let i = d.from.charCodeAt(0); (d.step > 0) ? (unlimited ? true : i < = d.to.charCodeAt(0)) : (i >= d.to.charCodeAt(0)); i += d.step) { yield String.fromCharCode(i); } } else { for (let i = d.from; (d.step > 0) ? (unlimited ? true : i < = d.to) : (i >= d.to); i += d.step) { yield i; } } }); 

Exemplos

levar

Exemplo 1.

take apenas leva tanto quanto pode chegar

take(10, range( {from: 100, step: 5, to: 120} ) )

retorna

[100, 105, 110, 115, 120]

Exemplo 2

to não necessário

take(10, range( {from: 100, step: 5} ) )

retorna

[100, 105, 110, 115, 120, 125, 130, 135, 140, 145]

leve tudo

Exemplo 3

from não necessário

takeAll( range( {to: 5} ) )

retorna

[0, 1, 2, 3, 4, 5]

Exemplo 4

takeAll( range( {to: 500, step: 100} ) )

retorna

[0, 100, 200, 300, 400, 500]

Exemplo 5

takeAll( range( {from: 'z', to: 'a'} ) )

retorna

["z", "y", "x", "w", "v", "u", "t", "s", "r", "q", "p", "o", "n", "m", "l", "k", "j", "i", "h", "g", "f", "e", "d", "c", "b", "a"]

você pode usar a function _.range(10) https://lodash.com/docs#range

Quanto a gerar uma matriz numérica para um determinado intervalo, eu uso isso:

 function range(start, stop) { var array = []; var length = stop - start; for (var i = 0; i < = length; i++) { array[i] = start; start++; } return array; } console.log(range(1, 7)); // [1,2,3,4,5,6,7] console.log(range(5, 10)); // [5,6,7,8,9,10] console.log(range(-2, 3)); // [-2,-1,0,1,2,3] 

Obviamente, não funcionará para matrizes alfabéticas.

O d3 também possui uma function de faixa interna. Veja https://github.com/mbostock/d3/wiki/Arrays#d3_range :

d3.range ([start,] stop [, passo])

Gera uma matriz contendo uma progressão aritmética, semelhante ao intervalo interno do Python. Esse método é usado frequentemente para iterar sobre uma sequência de valores numéricos ou inteiros, como os índices em uma matriz. Ao contrário da versão do Python, os argumentos não precisam ser inteiros, embora os resultados sejam mais previsíveis se forem devidos à precisão do ponto flutuante. Se a etapa for omitida, o padrão será 1.

Exemplo:

 d3.range(10) // returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

… mais alcance, usando uma function de gerador.

 function range(s, e, str){ // create generator that handles numbers & strings. function *gen(s, e, str){ while(s < = e){ yield (!str) ? s : str[s] s++ } } if (typeof s === 'string' && !str) str = 'abcdefghijklmnopqrstuvwxyz' const from = (!str) ? s : str.indexOf(s) const to = (!str) ? e : str.indexOf(e) // use the generator and return. return [...gen(from, to, str)] } // usage ... console.log(range('l', 'w')) //=> [ 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' ] console.log(range(7, 12)) //=> [ 7, 8, 9, 10, 11, 12 ] // first 'o' to first 't' of passed in string. console.log(range('o', 't', "ssshhhooooouuut!!!!")) // => [ 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 't' ] // only lowercase args allowed here, but ... console.log(range('m', 'v').map(v=>v.toUpperCase())) //=> [ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' ] // => and decreasing range ... console.log(range('m', 'v').map(v=>v.toUpperCase()).reverse()) // => ... and with a step console.log(range('m', 'v') .map(v=>v.toUpperCase()) .reverse() .reduce((acc, c, i) => (i % 2) ? acc.concat(c) : acc, [])) // ... etc, etc. 

Espero que isso seja útil.

Existe um módulo npm bereich para isso (“bereich” é a palavra alemã para “range”). Ele faz uso de iteradores de JavaScript modernos, para que você possa usá-lo de várias maneiras, como:

 console.log(...bereich(1, 10)); // => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 const numbers = Array.from(bereich(1, 10)); // => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] for (const number of bereich(1, 10)) { // ... } 

Ele também suporta intervalos descendentes (simplesmente trocando min e max ) e também suporta etapas diferentes de 1 .

Disclaimer: Eu sou o autor deste módulo, então por favor leve minha resposta com um grão de sal.

Fiquei surpreso ao encontrar este tópico e não ver nada como a minha solução (talvez eu tenha perdido uma resposta), então aqui está. Eu uso uma function de intervalo simples na syntax do ES6:

 // [begin, end[ const range = (b, e) => Array.apply(null, Array(e - b)).map((_, i) => {return i+b;}); 

Mas funciona apenas quando contando para a frente (ou seja, begin

 const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : bi;}); 

Aqui está um bom modo de fazer isso no ES6 apenas com números (não sei se compara sua velocidade):

 Array.prototype.map.call(' '.repeat(1 + upper - lower), (v, i) => i + lower) 

Para um intervalo de caracteres únicos, você pode modificá-lo ligeiramente:

 Array.prototype.map.call(' '.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt())); 

Conclua a implementação do ES6 usando assinatura de intervalo ([start,] stop [, step]):

 function range(start, stop, step=1){ if(!stop){stop=start;start=0;} return Array.from(new Array(int((stop-start)/step)), (x,i) => start+ i*step) } 

Se você quiser um passo negativo automático, adicione

 if(stop 

Ou mais minimalista:

 range=(b, e, step=1)=>{ if(!e){e=b;b=0} return Array.from(new Array(int((eb)/step)), (_,i) => b 

Se você tem grandes intervalos, veja a abordagem do gerador de Paolo Moretti

Eu encontrei uma function de intervalo JS equivalente à do PHP, e funciona incrivelmente bem aqui . Trabalha para frente e para trás e trabalha com números inteiros, flutuantes e alfabetos!

 function range(low, high, step) { // discuss at: http://phpjs.org/functions/range/ // original by: Waldo Malqui Silva // example 1: range ( 0, 12 ); // returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] // example 2: range( 0, 100, 10 ); // returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100] // example 3: range( 'a', 'i' ); // returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] // example 4: range( 'c', 'a' ); // returns 4: ['c', 'b', 'a'] var matrix = []; var inival, endval, plus; var walker = step || 1; var chars = false; if (!isNaN(low) && !isNaN(high)) { inival = low; endval = high; } else if (isNaN(low) && isNaN(high)) { chars = true; inival = low.charCodeAt(0); endval = high.charCodeAt(0); } else { inival = (isNaN(low) ? 0 : low); endval = (isNaN(high) ? 0 : high); } plus = ((inival > endval) ? false : true); if (plus) { while (inival < = endval) { matrix.push(((chars) ? String.fromCharCode(inival) : inival)); inival += walker; } } else { while (inival >= endval) { matrix.push(((chars) ? String.fromCharCode(inival) : inival)); inival -= walker; } } return matrix; } 

E aqui está a versão minificada:

 function range(h,c,b){var i=[];var d,f,e;var a=b||1;var g=false;if(!isNaN(h)&&!isNaN(c)){d=h;f=c}else{if(isNaN(h)&&isNaN(c)){g=true;d=h.charCodeAt(0);f=c.charCodeAt(0)}else{d=(isNaN(h)?0:h);f=(isNaN(c)?0:c)}}e=((d>f)?false:true);if(e){while(d< =f){i.push(((g)?String.fromCharCode(d):d));d+=a}}else{while(d>=f){i.push(((g)?String.fromCharCode(d):d));d-=a}}return i}; 

Para uma abordagem mais ruby ​​com boa compatibilidade com versões anteriores:

range([begin], end = 0) onde begin e end são números

 var range = function(begin, end) { if (typeof end === "undefined") { end = begin; begin = 0; } var result = [], modifier = end > begin ? 1 : -1; for ( var i = 0; i < = Math.abs(end - begin); i++ ) { result.push(begin + i * modifier); } return result; } 

Exemplos:

 range(3); //=> [0, 1, 2, 3] range(-2); //=> [0, -1, -2] range(1, 2) //=> [1, 2] range(1, -2); //=> [1, 0, -1, -2]