¿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 laRange
clase 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
stop
sea mayor questart
(y cámbielos si no).start >= stop
es 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 >= stop
no 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()]
const
tanto como sea posible, pero aquí solo será una referencia a la matriz, por lo que la matriz aún sería editable: 'Dconst
se 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
yield
palabra clave, y son universalmente compatibles en todas las plataformas. Aquí se puede encontrar un ejemplo delrange()
uso perezoso .yield
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 axrange
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
fuente
step
argumento 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 ).range
tiene 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 2
fuente
step
parámetro, pero cuandostop
no se pasa en tantostart
ystop
tienen que ser modificado. Lo actualizaréLas bibliotecas de utilidades underscore.js y lodash
range
proporcionan 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
Number
prototipoNumber.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ón
como 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
0
ystop
y 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 loop
En contraste con @ Tadeck de , @ de Volv y @ de janka102 respuesta que el retorno
[]
,undefined
o entrar en un bucle infinito cuandostep
se evalúa como0
oNaN
, 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
pythonic
imita el pitónrange
comportamiento mejor que puede usar generadores JS'(yield
), apoyando tanto lasrange(stop)
yrange(start, stop, step)
los casos de uso. Además,pythonic
larange
función 'devuelve unIterator
objeto similar a Python que admitemap
yfilter
, 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 wouldBeInvokedFiveTimes
Instalar usando
npm
:npm install --save pythonic
Divulgació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.from
método capaz de construir una matriz a partir de cualquier objeto que tenga unalength
propiedad. Entonces, pasar un objeto simple con solo lalength
propiedad creará un ArrayIterator que producirá unalength
cantidad 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
es6
implementació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
-20
hasta-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
in
operador (como python), debe usarof
. Por tanto, lai
variable 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 // 4
No puede hacer eso con una matriz no inicializada:
Array(5).forEach((_, index) => console.log(index)) // undefined
Pero, ¿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 4
fuente