¿JavaScript tiene un método como “range ()” para generar un rango dentro de los límites provistos?

En PHP, puedes hacer …

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

Es decir, hay una función que le permite obtener un rango de números o caracteres al pasar los límites superior e inferior.

¿Hay algo incorporado en JavaScript de forma nativa para esto? Si no, ¿cómo lo implementaría?

Números

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

Iteración de personaje

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

Como funciones

 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 funciones mecanografiadas

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

Función lodash.js _.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" 

Antiguos navegadores no es6 sin biblioteca:

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

Para los números, puede usar ES6 Array.from() , que funciona en todo estos días excepto IE:

Versión más corta:

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

Versión más larga:

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

que crea una matriz de 0 a 19 inclusive. Esto se puede acortar aún más a una de estas formas:

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

Los límites inferior y superior se pueden especificar también, por ejemplo:

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

Un artículo que describe esto con más detalle: http://www.2ality.com/2014/05/es6-array-methods.html

Aquí están mis 2 centavos:

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

Funciona para caracteres y números, yendo hacia adelante o hacia atrás con un paso 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 .

Si lo tuyo es boost los tipos nativos, Array.range 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)); 

Mi nuevo formulario favorito ( ES2015 )

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

Y si necesita una función con un param 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'] 

De acuerdo, en JavaScript no tenemos una función de range() como PHP , así que necesitamos crear la función que es bastante fácil, escribo un par de funciones de una línea para usted y las separo para Números y Alfabetos de la siguiente manera:

para Números :

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

y llámalo así:

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

y llámalo así:

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

función de rango simple:

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

Función práctica para hacer el truco, ejecute el fragmento de código a continuación

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

El Javascript estándar no tiene una función incorporada para generar rangos. Varios frameworks de JavaScript agregan soporte para tales características, o como otros han señalado, siempre puedes hacer tu propio.

Si desea verificarlo dos veces, el recurso definitivo es el estándar ECMA-262 .

Usando Harmony spread operator y funciones de flecha:

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

Ejemplo:

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

Hice algunas investigaciones sobre algunas diversas funciones de rango. Verifique la comparación jsperf de las diferentes formas de hacer estas funciones. Ciertamente no es una lista perfecta o exhaustiva, pero debería ayudar 🙂

El ganador es…

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

Técnicamente no es el más rápido en Firefox, pero la increíble diferencia de velocidad (imho) en Chrome lo compensa.

También es interesante observar cuánto más rápido es Chrome con estas funciones de matriz que Firefox. Chrome es al menos 4 o 5 veces más rápido .

Un desafío interesante sería escribir la función más corta para hacer esto. Recursion al rescate!

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

Tiende a ser lento en rangos grandes, pero afortunadamente las computadoras cuánticas están a la vuelta de la esquina.

Una ventaja adicional es que es ofuscante. Porque todos sabemos lo importante que es esconder nuestro código de miradas indiscretas.

Para ofuscar de verdad y completamente la función, haz esto:

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

Yo codificaría algo como esto:

 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] 

Se comporta de manera similar al rango de Python:

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

Puede usar el range lodash o Undescore.js :

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

Alternativamente, si solo necesitas un rango consecutivo de enteros, puedes hacer algo como:

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

En la range ES6 se puede implementar con generadores :

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

Esta implementación ahorra memoria al iterar secuencias grandes, porque no tiene que materializar todos los valores en una matriz:

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

Se puede crear una implementación bastante minimalista que emplea mucho ES6 de la siguiente manera, con especial atención al método estático Array.from() :

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

Otra versión que usa generadores ES6 (vea la gran respuesta de Paolo Moretti con los generadores 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 ] 

O, si solo necesitamos iterable, entonces:

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

Aunque esto no es de PHP , sino una imitación de range de 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 generadores Harmony , compatibles con todos los navegadores excepto 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; } } }); 

Ejemplos

tomar

Ejemplo 1.

take solo lleva todo lo que puede obtener

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

devoluciones

[100, 105, 110, 115, 120]

Ejemplo 2

no necesario

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

devoluciones

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

tomalo todo

Ejemplo 3.

from no necesario

takeAll( range( {to: 5} ) )

devoluciones

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

Ejemplo 4.

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

devoluciones

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

Ejemplo 5.

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

devoluciones

["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"]

puede usar la función _.range(10) https://lodash.com/docs#range

En cuanto a generar una matriz numérica para un rango dado, uso esto:

 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, no funcionará para arreglos alfabéticos.

d3 también tiene una función de rango incorporada. Ver https://github.com/mbostock/d3/wiki/Arrays#d3_range :

d3.range ([inicio,] detener [, paso])

Genera una matriz que contiene una progresión aritmética, similar al rango incorporado de Python. Este método se usa a menudo para iterar sobre una secuencia de valores numéricos o enteros, como los índices en una matriz. A diferencia de la versión de Python, no se requiere que los argumentos sean enteros, aunque los resultados son más predecibles si se deben a la precisión del punto flotante. Si se omite el paso, se establece de manera predeterminada en 1.

Ejemplo:

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

… más scope, usando una función de generador.

 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 esto sea útil.

Hay un módulo npm para eso (“bereich” es la palabra alemana para “rango”). Hace uso de los iteradores de JavaScript modernos, por lo que puede usarlo de varias maneras, como por ejemplo:

 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)) { // ... } 

También admite rangos descendentes (simplemente intercambiando min y max ), y también admite pasos distintos de 1 .

Descargo de responsabilidad: soy el autor de este módulo, así que por favor tome mi respuesta con un grano de sal.

Me sorprendió encontrar este hilo y no ver nada como mi solución (tal vez me perdí una respuesta), así que aquí está. Utilizo una función de rango simple en la syntax de ES6:

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

Pero solo funciona al contar hacia adelante (es decir, comenzar

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

Aquí hay una buena forma de hacerlo en ES6 solo con números (no sé cómo se compara su velocidad):

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

Para un rango de caracteres individuales, puede modificarlo ligeramente:

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

Implementación completa de ES6 usando la firma range ([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) } 

Si quiere un paso negativo automático, agregue

 if(stop 

O más minimalistamente:

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

Si tienes rangos enormes mira el enfoque de generador de Paolo Moretti

Encontré una función de rango JS equivalente a la de PHP, y funciona increíblemente bien aquí . Funciona hacia adelante y hacia atrás, y funciona con enteros, flotantes y 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; } 

Y aquí está la versión 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 un enfoque más ruby ​​con buena compatibilidad con versiones anteriores:

range([begin], end = 0) donde begin y end son 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; } 

Ejemplos:

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