Búsqueda de sitios web

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

Artículos relacionados