¿Existe una función en JavaScript similar a la de Python range()?
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;
}
javascript
python
clwen
fuente
fuente

range()en que funciona en Python, para que pueda usarla. No existe tal función en JavaScript, pero hay algunos complementos para diferentes marcos, como laRangeclase para MooTools .Respuestas:
No , no hay ninguno, pero puedes hacer uno .
Implementación de JavaScript de Python
range()Tratando de 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; };Vea este jsfiddle para una prueba.
Comparación entre
range()JavaScript y PythonFunciona 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 de 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) []Entonces, si necesita una función que funcione de manera similar a la de Python
range(), puede usar la solución mencionada anteriormente.fuente
stopsea mayor questart(y cámbielos si no).start >= stopes necesario llevar a una matriz vacía si el objetivo es realmente emular el rango de Python. Y yo diría que es más intuitivo de todos modos.start >= stopno es suficiente para que esta función se comporte comorange()en Python. He actualizado mi respuesta.Para un rango muy simple en ES6:
let range = n => Array.from(Array(n).keys())Del comentario de bigOmega , esto se puede acortar usando la sintaxis de Spread :
let range = n => [...Array(n).keys()]fuente
let range = n => [...Array(n).keys()]consttanto como sea posible, pero aquí solo será una referencia a la matriz, por lo que la matriz aún sería editable: 'Dconstse aplicaría a la función en sí, no a su valor de retorno. Probablemente no desee modificar la función de ninguna manera.2018: esta respuesta sigue recibiendo votos a favor, así que aquí hay una actualización. El código a continuación es obsoleto, pero afortunadamente los generadores estandarizados ES6 y la
yieldpalabra clave, y son universalmente compatibles en todas las plataformas. Aquí se puede encontrar un ejemplo delrange()uso perezoso .yieldAdemá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 axrangeen 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,5fuente
stepargumento y probarlo con los valores de mi respuesta ? Su respuesta es excelente para las aplicaciones en las que tenemos navegadores muy específicos en mente (no funcionará en Google Chrome, Safari e IE versiones anteriores a la 9: stackoverflow.com/a/2209743/548696 ).rangetiene el "último" valor excluido (por lo que se debe usar en>=lugar del>código anterior)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, necesita 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 2fuente
stepparámetro, pero cuandostopno se pasa en tantostartystoptienen que ser modificado. Lo actualizaréLas bibliotecas de utilidades underscore.js y lodash
rangeproporcionan un puerto de la función de Python 2 (junto con muchas otras herramientas útiles). Ejemplos copiados de los documentos de subrayado:_.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); => []fuente
Se puede lograr adjuntando un iterador al
NumberprototipoNumber.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
fuente
Aquí hay una pequeña extensión para una de las respuestas en caso de que necesite especificar la posición inicial y final del rango:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);fuente
Aqui tienes.
Esto escribirá (o sobrescribirá) el valor de cada índice con el número de índice.
Array.prototype.writeIndices = function( n ) { for( var i = 0; i < (n || this.length); ++i ) this[i] = i; return this; };Si no proporciona un número, utilizará la longitud actual de la matriz.
Úselo así:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]fuente
Para obtener una variedad de tamaños
x, aquí hay una sola línea sin usar ninguna bibliotecavar range = n => Array(n + 1).join(1).split('').map((x, i) => i)trabaja como
> range(4) [0, 1, 2, 3]fuente
var range = n => Array(n).fill().map((e, i) => i);x' cuando en realidad lo usóncomo nombre de parámetroLa siguiente es una adaptación natural de la función range () de Python a JavaScript:
// Generate range from start (inclusive) to stop (exclusive): function* range(start, stop, step = 1) { if (stop === undefined) [start, stop] = [0, start]; if (step > 0) while (start < stop) yield start, start += step; else if (step < 0) while (start > stop) yield start, start += step; else throw new RangeError('range() step argument invalid'); } // Examples: console.log([...range(3)]); // [0, 1, 2] console.log([...range(0, 3)]); // [0, 1, 2] console.log([...range(0, 3, -1)]);// [] console.log([...range(0, 0)]); // [] console.log([...range(-3)]); // [] console.log([...range(-3, 0)]); // [-3, -2, -1]Es compatible con cualquier argumento que puede ser comparado a
0ystopy puede ser incrementado porstep. Se comporta de manera idéntica a la versión de Python cuando se usa con números que no excedenNumber.MAX_SAFE_INTEGER.Tenga en cuenta los siguientes casos de esquina:
[...range(0, 0, 0)]; // RangeError: range() step argument invalid [...range(Number.MAX_SAFE_INTEGER + 1, Number.MAX_SAFE_INTEGER + 2)]; // [] [...range(Number.MAX_SAFE_INTEGER + 2, Number.MAX_SAFE_INTEGER + 3)]; // Infinite loop [...range(0.7, 0.8, 0.1)]; // [0.7, 0.7999999999999999] [...range('1', '11')]; // ['1'] [...range('2', '22')]; // Infinite loopEn contraste con @ Tadeck de , @ de Volv y @ de janka102 respuesta que el retorno
[],undefinedo entrar en un bucle infinito cuandostepse evalúa como0oNaN, esta función generador genera una excepción similar al comportamiento del pitón.fuente
Más refinado con los parámetros predeterminados de ES6.
let range = function*(start = 0, stop, step = 1) { let cur = (stop === undefined) ? 0 : start; let max = (stop === undefined) ? start : stop; for (let i = cur; step < 0 ? i > max : i < max; i += step) yield i }fuente
pythonicimita el pitónrangecomportamiento mejor que puede usar generadores JS'(yield), apoyando tanto lasrange(stop)yrange(start, stop, step)los casos de uso. Además,pythoniclarangefunción 'devuelve unIteratorobjeto similar a Python que admitemapyfilter, por lo que uno podría hacer frases ingeniosas como:import {range} from 'pythonic'; // ... const results = range(5).map(wouldBeInvokedFiveTimes); // `results` is now an array containing elements from // 5 calls to wouldBeInvokedFiveTimesInstalar usando
npm:npm install --save pythonicDivulgación Soy autor y mantenedor de Pythonic
fuente
MDN recomienda este enfoque: generador de secuencia (rango)
// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc) const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step)); // Generate numbers range 0..4 console.log("range(0, 4, 1):", range(0, 4, 1)); // [0, 1, 2, 3, 4] // Generate numbers range 1..10 with step of 2 console.log("\nrange(1, 10, 2):", range(1, 10, 2)); // [1, 3, 5, 7, 9] // Generate the alphabet using Array.from making use of it being ordered as a sequence console.log("\nrange('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))", range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))); // ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]fuente
Puede utilizar la biblioteca de subrayado . Contiene docenas de funciones útiles para trabajar con matrices y muchas más.
fuente
Todas las soluciones aquí se refieren al rango de Python 2 (probablemente debido al ejemplo de código que dio). Sin embargo, en Python 3, el método range () devuelve un iterador. JavaScript también tiene iteradores y son más eficientes en el espacio que generar toda la matriz y almacenarla en la memoria.
Entonces, la representación más precisa de la
range(n)función de Python 3 esArray(n).keys().Por ejemplo:
for (let i of Array(n).keys()) { console.log(i) // 0, 1, 2, 3, ..., n }Un ejemplo más (que ya se ha cubierto en las otras respuestas). Conversión del iterador en una matriz (ES6):
let ary = [...Array(n).keys()]; // ary = [0, 1, 2, 3, ..., n]fuente
Aún no hay una función incorporada que sea equivalente
range(), pero con la versión más reciente, ES2015, puede crear su propia implementación. Aquí tienes una versión limitada. Limitado porque no tiene en cuenta el parámetro de paso. Solo min, max.const range = (min = null, max = null) => Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)Esto se logra mediante el
Array.frommétodo capaz de construir una matriz a partir de cualquier objeto que tenga unalengthpropiedad. Entonces, pasar un objeto simple con solo lalengthpropiedad creará un ArrayIterator que producirá unalengthcantidad de objetos.fuente
Esta es mi forma preferida. Te permite especificar una o dos entradas como en Python.
function range(start, end) { return Array.from(Array(end||start).keys()).slice(!!end*start) }fuente
Aquí hay otra
es6implementación de la gama.// range :: (from, to, step?) -> [Number] const range = (from, to, step = 1) => { //swap values if necesery [from, to] = from > to ? [to, from] : [from, to] //create range array return [...Array(Math.round((to - from) / step))] .map((_, index) => { const negative = from < 0 ? Math.abs(from) : 0 return index < negative ? from + index * step : (index - negative + 1) * step }) } range(-20, 0, 5) .forEach(val => console.log(val)) for(const val of range(5, 1)){ console.log(`value ${val}`) }fuente
-20hasta-30?No, no hay ninguno, pero puedes hacer uno.
Soy parcial al comportamiento de rango de Python3. A continuación, encontrará la implementación de JavaScript del rango de Python ():
function* range(start=0, end=undefined, step=1) { if(arguments.length === 1) {end = start, start = 0} [...arguments].forEach(arg => { if( typeof arg !== 'number') {throw new TypeError("Invalid argument")} }) if(arguments.length === 0) {throw new TypeError("More arguments neede")} if(start >= end) return yield start yield* range(start + step, end, step) } // Use Cases console.log([...range(5)]) console.log([...range(2, 5)]) console.log([...range(2, 5, 2)]) console.log([...range(2,3)]) // You can, of course, iterate through the range instance.fuente
Suponiendo que necesita un rango simple con un solo paso:
let range = (start, end)=> { if(start === end) return [start]; return [start, ...range(start + 1, end)]; }más
let range = (start, end, step)=> { if(start === end) return [start]; return [start, ...range(start + step, end)]; }consulte aquí para obtener más información.
fuente
Como respondí antes: no , no lo hay. Pero puedes hacer el tuyo propio. Creo que este es un enfoque interesante para ES6. Funciona de manera muy similar a Python 2.7
range(), pero es mucho más dinámico.function range(start, stop, step = 1) { // This will make the function behave as range(stop) if(arguments.length === 1) { return [...Array(arguments[0]).keys()] } // Adjusts step to go towards the stop value if((start > stop && !(step < 0)) || (start < stop && !(step > 0))) { step *= -1 } let returnArray = [] // Checks if i is in the interval between start and stop no matter if stop // is lower than start or vice-versa for(let i = start; (i-start)*(i-stop) <= 0; i += step) { returnArray.push(i) } return returnArray }Esta función puede comportarse de tres formas diferentes (como el range () de Python):
range(stop)range(start, stop)range(start, stop, step)Estos ejemplos:
console.log(range(5)) console.log(range(-2, 2)) console.log(range(2, -2)) console.log(range(10, 20, 2))Le dará el siguiente resultado:
[ 0, 1, 2, 3, 4 ] [ -2, -1, 0, 1, 2 ] [ 2, 1, 0, -1, -2 ] [ 10, 12, 14, 16, 18, 20 ]Tenga en cuenta que en lugar de iterar sobre la matriz con el
inoperador (como python), debe usarof. Por tanto, laivariable asume el valor, y no el índice, del elemento de la matriz.for(let i of range(5)) { // do something with i... }fuente
Una opción para NodeJs es usar un búfer:
[...Buffer.alloc(5).keys()] // [ 0, 1, 2, 3, 4 ]Lo bueno es que puede iterar directamente en el búfer:
Buffer.alloc(5).forEach((_, index) => console.log(index)) // 0 // 1 // 2 // 3 // 4No puede hacer eso con una matriz no inicializada:
Array(5).forEach((_, index) => console.log(index)) // undefinedPero, ¿quién en su sano juicio usa un búfer para un propósito como este;)
fuente
Así es como lo hago
let n = 5 [...Array(n).keys()].map(x=>{console.log(x)})salida
0 1 2 3 4fuente