Función de JavaScript similar a range() de Python
¿Existe una función en JavaScript similar a range() de Python?
Creo que debería haber una mejor manera que escribir las siguientes líneas cada vez:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
Respuesta #1
Para un rango muy simple en ES6:
let range = n => Array.from(Array(n).keys())
Según el comentario de bigOmega, esto se puede acortar usando la sintaxis Spread:
let range = n => [...Array(n).keys()]
Respuesta #2
No, no hay ninguno, pero puedes hacer uno.
La implementación de JavaScript de range() de Python
Intentando emular cómo funciona en Python, crearía una función similar a esta:
function range(start, stop, step) {
if (typeof stop == 'undefined') {
// one param defined
stop = start;
start = 0;
}
if (typeof step == 'undefined') {
step = 1;
}
if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
return [];
}
var result = [];
for (var i = start; step > 0 ? i < stop : i > stop; i += step) {
result.push(i);
}
return result;
};
Mira este jsfiddle como prueba.
Comparación entre range() en JavaScript y Python
Funciona de la siguiente manera:
range(4)devuelve[0, 1, 2, 3],range(3,6)devuelve[3, 4, 5],range(0,10,2)devuelve[0, 2, 4, 6, 8],range(10,0,-1)devuelve[10, 9, 8, 7, 6, 5, 4, 3, 2, 1],range(8,2,-2)devuelve[8, 6, 4],range(8,2)devuelve[],range(8,2,2)devuelve[],range(1,5,-1)devuelve[],range(1,5,-2)devuelve[],
y su contraparte en Python funciona exactamente de la misma manera (al menos en los casos mencionados):
>>> range(4)
[0, 1, 2, 3]
>>> range(3,6)
[3, 4, 5]
>>> range(0,10,2)
[0, 2, 4, 6, 8]
>>> range(10,0,-1)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> range(8,2,-2)
[8, 6, 4]
>>> range(8,2)
[]
>>> range(8,2,2)
[]
>>> range(1,5,-1)
[]
>>> range(1,5,-2)
[]
Así que si necesitas que una función funcione de manera similar a range() de Python, puedes usar la solución mencionada arriba.
Respuesta #3
Fusionando ambas respuestas de @Tadeck y @georg, se me ocurrió esto:
function* range(start, stop, step = 1) {
if (stop == null) {
// one param defined
stop = start;
start = 0;
}
for (let i = start; step > 0 ? i < stop : i > stop; i += step) {
yield i;
}
}
Para usarlo en un bucle for necesitas el bucle for-of de ES6/JS1.7:
for (let i of range(5)) {
console.log(i);
}
// Outputs => 0 1 2 3 4
for (let i of range(0, 10, 2)) {
console.log(i);
}
// Outputs => 0 2 4 6 8
for (let i of range(10, 0, -2)) {
console.log(i);
}
// Outputs => 10 8 6 4 2
Respuesta #4
2018: esta respuesta sigue recibiendo votos positivos, así que aquí hay una actualización. El código a continuación está obsoleto, pero afortunadamente ES6 estandarizó los generadores y la palabra clave yield, y son compatibles de manera universal en todas las plataformas. Un ejemplo del range() perezoso usando yield se puede encontrar aquí.
Además de lo que ya se ha dicho, Javascript 1.7+ proporciona soporte para iteradores y generadores que se pueden usar para crear una versión perezosa y eficiente en memoria de range, similar a xrange en Python2:
function range(low, high) {
return {
__iterator__: function() {
return {
next: function() {
if (low > high)
throw StopIteration;
return low++;
}
}
}
}
}
for (var i in range(3, 5))
console.log(i); // 3,4,5
Respuesta #5
Una versión de la función range de Python 2 es proporcionada por las bibliotecas de utilidad underscore.js y lodash (junto con muchas otras herramientas útiles). Ejemplos copiados de la documentación de underscore:
_.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);
=> []
Respuesta #6
Se puede lograr adjuntando un iterador al prototipo Number
Number.prototype[Symbol.iterator] = function* () {
for (var i = 0; i <= this; i++) {
yield i
}
}
[...5] // will result in [0,1,2,3,4,5]
Tomado del curso de Kyle Simpson Rethinking Asynchronous JavaScript
Respuesta #7
Aquí hay una pequeña extensión para una de las respuestas en caso de que necesites especificar tanto la posición inicial como la final del rango:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
