objetos - object javascript
¿Tiene JavaScript un método como "rango()" para generar un rango dentro de los límites proporcionados? (30)
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 integrado en JavaScript de forma nativa para esto? Si no, ¿cómo lo implementaría?
... más rango, 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.
Aquí están mis 2 centavos:
function range(start, count) {
return Array.apply(0, Array(count))
.map(function (element, index) {
return index + start;
});
}
Aquí hay una buena manera de hacerlo en ES6 solo con números (no sé su velocidad se compara):
Array.prototype.map.call('' ''.repeat(1 + upper - lower), (v, i) => i + lower)
Para un rango de caracteres individuales, puedes modificarlo ligeramente:
Array.prototype.map.call('' ''.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt()));
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]
Complete la implementación de ES6 utilizando la firma de rango ([inicio,] parada [, paso])
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 quieres escalones negativos automáticos, agrega
if(stop<start)step=-Math.abs(step)
O más minimalista:
range=(b, e, step=1)=>{
if(!e){e=b;b=0}
return Array.from(new Array(int((e-b)/step)), (_,i) => b<e? b+i*step : b-i*step)
}
Si tienes rangos enormes mira el enfoque del generador de Paolo Moretti
El Javascript estándar no tiene una función incorporada para generar rangos. Varios marcos de javascript agregan soporte para tales características, o como otros lo han señalado, siempre puede hacer su propio rollo.
Si desea volver a verificar, el recurso definitivo es el estándar ECMA-262 .
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 matrices alfabéticas.
Encontré una función de rango JS equivalente a la de PHP, y funciona increíblemente bien here . ¡Trabaja hacia adelante y hacia atrás, y trabaja con enteros, flotadores 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};
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));
aquí es cómo usarlo
rango (Inicio, Fin, Paso = 1, Desplazamiento = 0);
- inclusive -
range(5,10) // [5, 6, 7, 8, 9, 10]
avancerange(5,10) // [5, 6, 7, 8, 9, 10]
- inclusive -
range(10,5) // [10, 9, 8, 7, 6, 5]
hacia atrásrange(10,5) // [10, 9, 8, 7, 6, 5]
- paso -
range(10,2,2) // [10, 8, 6, 4, 2]
hacia atrásrange(10,2,2) // [10, 8, 6, 4, 2]
- exclusivo -
range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
avancerange(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
- desplazamiento - ampliar el
range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
- desplazamiento -
range(5,10,0,-2) // [7, 8]
contracciónrange(5,10,0,-2) // [7, 8]
- paso - ampliar el
range(10,0,2,2) // [12, 10, 8, 6, 4, 2, 0, -2]
Esperamos que te sea útil.
Y aquí es cómo funciona.
Básicamente, primero estoy calculando la longitud de la matriz resultante y creo una matriz rellena con cero para esa longitud, luego la relleno con los valores necesarios
-
(step || 1)
=> Y otros como este significa usar el valor delstep
y si no se proporcionó, use1
lugar - Comenzamos calculando la longitud de la matriz de resultados utilizando
(Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1)
para hacerlo más simple (diferencia * offset) en ambas direcciones / paso - Después de obtener la longitud, creamos una matriz vacía con valores inicializados utilizando la
new Array(length).fill(0);
Chequea aquí - Ahora tenemos una matriz
[0,0,0,..]
a la longitud que queremos. LoArray.map(function() {})
y devolvemos una nueva matriz con los valores que necesitamos usandoArray.map(function() {})
-
var direction = start < end ? 1 : 0;
Obviamente, si elstart
no es más pequeño que elend
, necesitamos retroceder. Me refiero a pasar de 0 a 5 o viceversa. - En cada iteración, el
index
startingPoint
+stepSize
* nos da el valor que necesitamos
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 aumentar los tipos nativos, entonces 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));
Hay un módulo de bereich para eso ("bereich" es la palabra alemana para "rango"). Hace uso de los iteradores modernos de JavaScript, 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 a 1
.
Descargo de responsabilidad: Soy el autor de este módulo, así que tome mi respuesta con un grano de sal.
Hice una investigación sobre algunas funciones de rango diferentes. Compruebe 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 lo más rápido en Firefox, pero la diferencia de velocidad loca (imho) en Chrome lo compensa.
También es interesante observar cuánto más rápido es el cromo con estas funciones de matriz que Firefox. Chrome es al menos 4 o 5 veces más rápido .
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 sintaxis ES6:
// [begin, end[
const range = (b, e) => Array.apply(null, Array(e - b)).map((_, i) => {return i+b;});
Pero funciona solo cuando se cuenta hacia adelante (es decir, comienza <final), por lo que podemos modificarlo ligeramente cuando sea necesario de la siguiente manera:
const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : b-i;});
Mi nueva forma favorita ( ES2015 )
Array(10).fill(1).map((x, y) => x + y)
Y si necesitas una función con un step
param:
const range = (start, stop, step = 1) =>
Array(Math.ceil((stop - start) / step))
.fill(start)
.map((x, y) => x + y * step)
Otra versión que usa generadores ES6 (ver gran respuesta de Paolo Moretti con 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 lo necesitamos, 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);
}
Para los números puede usar ES6 Array.from()
, que funciona en todo en estos días, excepto en 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 puede reducirse aún más a una de estas formas:
Array.from(Array(20).keys())
// or
[...Array(20).keys()]
También se pueden especificar límites inferiores y superiores, 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
Puedes 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 necesita un rango consecutivo de enteros, puede 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 generators :
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);
}
También puedes hacer lo siguiente:
const range = Array.from(Array(size)).map((el, idx) => idx+1).slice(begin, end);
Un desafío interesante sería escribir la función más corta para hacer esto. ¡Recursión al rescate!
function r(a,b){return a>b?[]:[a].concat(r(++a,b))}
Tiende a ser lento en grandes rangos, pero afortunadamente las computadoras cuánticas están a la vuelta de la esquina.
Una ventaja añadida es que es ofuscante. Porque todos sabemos lo importante que es ocultar nuestro código de miradas indiscretas.
Para ofuscar verdadera y completamente la función, haga esto:
function r(a,b){return (a<b?[a,b].concat(r(++a,--b)):a>b?[]:[a]).sort(function(a,b){return a-b})}
Una implementación bastante minimalista que emplea ES6 en gran medida se puede crear de la siguiente manera, prestando especial atención al método estático Array.from()
:
const getRange = (start, stop) => Array.from(
new Array((stop - start) + 1),
(_, i) => i + start
);
Usando generadores Harmony , soportados por 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 toma tanto como puede conseguir
take(10, range( {from: 100, step: 5, to: 120} ) )
devoluciones
[100, 105, 110, 115, 120]
Ejemplo 2.
to
no ser 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"]
Usando el operador de propagación de Harmony y las 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 ]
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 forma similar a la gama Python:
>>> range(-4,2)
[-4, -3, -2, -1, 0, 1]
d3 también tiene una función de rango incorporada. Consulte https://github.com/mbostock/d3/wiki/Arrays#d3_range :
d3.range ([inicio,] parada [, 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, el valor predeterminado es 1.
Ejemplo:
d3.range(10)
// returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
función de rango simple:
function range(start, stop, step){
var a=[start], b=start;
while(b<stop){b+=(step || 1);a.push(b)}
return a;
};
puede utilizar la función _.range(10)
lodash
De acuerdo, en JavaScript no tenemos una función de range()
como PHP , por lo que necesitamos crear la función que es bastante fácil, escribo un par de funciones de una línea para ti 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 como
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 como
alphabetRange(''c'', ''h''); //["c", "d", "e", "f", "g"]
Números
[...Array(5).keys()];
=> [0, 1, 2, 3, 4]
Iteración de caracteres
String.fromCharCode(...[...Array(''D''.charCodeAt(0) - ''A''.charCodeAt(0) + 1).keys()].map(i => i + ''A''.charCodeAt(0)));
=> "ABCD"
Iteración
for (const x of Array(5).keys()) {
console.log(x, String.fromCharCode(''A''.charCodeAt(0) + x));
}
=> 0,"A" 1,"B" 2,"C" 3,"D" 4,"E"
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<number> {
return [...Array(size).keys()].map(i => i + startAt);
}
function characterRange(startChar:string, endChar:string):ReadonlyArray<string> {
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 una biblioteca:
Array.apply(null, Array(5)).map(function (_, i) {return i;});
=> [0, 1, 2, 3, 4]
console.log([...Array(5).keys()]);
Gracias.
(Crédito ES6 para nils petersohn y otros comentaristas)
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'']
var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);