JavaScript ha un metodo come “range ()” per generare un intervallo all’interno dei limiti forniti?

In PHP, puoi fare …

range(1, 3); // Array(1, 2, 3) range("A", "C"); // Array("A", "B", "C") 

Cioè, c’è una funzione che ti consente di ottenere un intervallo di numeri o caratteri passando i limiti superiore e inferiore.

C’è qualcosa di integrato in JavaScript in modo nativo per questo? In caso contrario, come lo implementerei?

Numeri

 [...Array(5).keys()]; => [0, 1, 2, 3, 4] 

Iterazione del personaggio

 String.fromCharCode(...[...Array('D'.charCodeAt(0) - 'A'.charCodeAt(0) + 1).keys()].map(i => i + 'A'.charCodeAt(0))); => "ABCD" 

Come funzioni

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

Come funzioni digitate

 function range(size:number, startAt:number = 0):ReadonlyArray { return [...Array(size).keys()].map(i => i + startAt); } function characterRange(startChar:string, endChar:string):ReadonlyArray { return String.fromCharCode(...range(endChar.charCodeAt(0) - startChar.charCodeAt(0), startChar.charCodeAt(0))) } 

funzione 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" 

Vecchi browser non es6 senza una libreria:

 Array.apply(null, Array(5)).map(function (_, i) {return i;}); => [0, 1, 2, 3, 4] 
 console.log([...Array(5).keys()]); 

Per i numeri è ansible utilizzare ES6 Array.from() , che funziona in tutti questi giorni tranne IE:

Versione più breve:

 Array.from({length: 20}, (x,i) => i); 

Versione più lunga:

 Array.from(new Array(20), (x,i) => i) 

che crea una matrice da 0 a 19 inclusi. Questo può essere ulteriormente abbreviato in una di queste forms:

 Array.from(Array(20).keys()) // or [...Array(20).keys()] 

È ansible specificare anche i limiti inferiore e superiore, ad esempio:

 Array.from(new Array(20), (x,i) => i + *lowerBound*) 

Un articolo che descrive questo in modo più dettagliato: http://www.2ality.com/2014/05/es6-array-methods.html

Ecco i miei 2 centesimi:

  function range(start, count) { return Array.apply(0, Array(count)) .map(function (element, index) { return index + start; }); } 

Funziona per personaggi e numeri, andando avanti o indietro con un passaggio opzionale.

 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 .

Se i tipi nativi aumentanti sono la tua Array.range , allora assegnali 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)); 

La mia nuova forma preferita ( ES2015 )

 Array(10).fill(1).map((x, y) => x + y) 

E se hai bisogno di una funzione con un parametro step :

 const range = (start, stop, step = 1) => Array(Math.ceil((stop - start) / step)) .fill(start) .map((x, y) => x + y * step) 
 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'] 

OK, in JavaScript non abbiamo una funzione range() come PHP , quindi abbiamo bisogno di creare la funzione che è abbastanza semplice, scrivo un paio di funzioni a riga singola per te e le separo per Numeri e Alfabeti come di seguito:

per i numeri :

 function numberRange (start, end) { return new Array(end - start).fill().map((d, i) => i + start); } 

e chiamalo come:

 numberRange(5, 10); //[5, 6, 7, 8, 9] 

per gli alfabeti :

 function alphabetRange (start, end) { return new Array(end.charCodeAt(0) - start.charCodeAt(0)).fill().map((d, i) => String.fromCharCode(i + start.charCodeAt(0))); } 

e chiamalo come:

 alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"] 

funzione gamma semplice:

 function range(start, stop, step){ var a=[start], b=start; while(b 
 var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l); 

Comoda funzione per fare il trucco, eseguire il frammento di codice qui sotto

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

Il Javascript standard non ha una funzione integrata per generare intervalli. Diverse strutture javascript aggiungono il supporto per tali funzionalità o, come altri hanno sottolineato, puoi sempre eseguire il rollover.

Se si desidera ricontrollare, la risorsa definitiva è lo standard ECMA-262 .

Usando l’Harmony diffondere le funzioni dell’operatore e della freccia:

 var range = (start, end) => [...Array(end - start + 1)].map((_, i) => start + i); 

Esempio:

 range(10, 15); [ 10, 11, 12, 13, 14, 15 ] 

Ha fatto qualche ricerca su alcune varie funzioni di gamma. Controlla il confronto jsperf dei diversi modi per eseguire queste funzioni. Certamente non un elenco perfetto o esauriente, ma dovrebbe aiutare 🙂

Il vincitore è…

 function range(lowEnd,highEnd){ var arr = [], c = highEnd - lowEnd + 1; while ( c-- ) { arr[c] = highEnd-- } return arr; } range(0,31); 

Tecnicamente non è il più veloce su firefox, ma la pazzesca differenza di velocità (imho) su Chrome compensa.

Un’altra osservazione interessante è quanto Chrome sia più veloce con queste funzioni di array rispetto a Firefox. Chrome è almeno 4 o 5 volte più veloce .

Una sfida interessante sarebbe scrivere la funzione più breve per farlo. Ricorsione al salvataggio!

 function r(a,b){return a>b?[]:[a].concat(r(++a,b))} 

Tende ad essere lento su grandi distanze, ma fortunatamente i computer quantistici sono proprio dietro l’angolo.

Un ulteriore vantaggio è che è offuscato. Perché sappiamo tutti quanto sia importante hide il nostro codice da occhi indiscreti.

Per offuscare veramente e completamente la funzione, fai questo:

 function r(a,b){return (ab?[]:[a]).sort(function(a,b){return ab})} 

Vorrei scrivere qualcosa come questo:

 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] 

Si comporta in modo simile alla gamma Python:

 >>> range(-4,2) [-4, -3, -2, -1, 0, 1] 

Puoi usare la range lodash o Undescore.js :

 var range = require('lodash/range') range(10) // -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] 

In alternativa, se hai solo bisogno di un intervallo consecutivo di numeri interi puoi fare qualcosa del tipo:

 Array.apply(undefined, { length: 10 }).map(Number.call, Number) // -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] 

Nella range ES6 può essere implementato con i generatori :

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

Questa implementazione salva la memoria durante l'iterazione di sequenze di grandi dimensioni, perché non deve materializzare tutti i valori in una matrice:

 for (let i of range(1, oneZillion)) { console.log(i); } 

Un’implementazione piuttosto minimalista che utilizza pesantemente ES6 può essere creata come segue, con particolare attenzione al metodo statico Array.from() :

 const getRange = (start, stop) => Array.from( new Array((stop - start) + 1), (_, i) => i + start ); 

Un’altra versione che utilizza i generatori ES6 (vedi la grande risposta di Paolo Moretti con i generatori 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 ] 

Oppure, se abbiamo solo bisogno di iterable, allora:

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

Anche se questo non è da PHP , ma un’imitazione range da 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] 

Utilizzo dei generatori Harmony , supportati da tutti i browser tranne 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; } } }); 

Esempi

prendere

Esempio 1.

take solo prende quanto può ottenere

take(10, range( {from: 100, step: 5, to: 120} ) )

ritorna

[100, 105, 110, 115, 120]

Esempio 2.

non necessario

take(10, range( {from: 100, step: 5} ) )

ritorna

[100, 105, 110, 115, 120, 125, 130, 135, 140, 145]

prendi tutto

Esempio 3.

from non necessario

takeAll( range( {to: 5} ) )

ritorna

[0, 1, 2, 3, 4, 5]

Esempio 4.

takeAll( range( {to: 500, step: 100} ) )

ritorna

[0, 100, 200, 300, 400, 500]

Esempio 5.

takeAll( range( {from: 'z', to: 'a'} ) )

ritorna

["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"]

puoi usare la funzione _.range(10) https://lodash.com/docs#range

Per quanto riguarda la generazione di un array numerico per un determinato intervallo, lo uso:

 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] 

Ovviamente, non funzionerà con gli array alfabetici.

d3 ha anche una funzione di intervallo incorporato. Vedi https://github.com/mbostock/d3/wiki/Arrays#d3_range :

d3.range ([start,] stop [, step])

Genera una matrice contenente una progressione aritmetica, simile all’intervallo incorporato di Python. Questo metodo viene spesso utilizzato per iterare su una sequenza di valori numerici o interi, come gli indici in una matrice. A differenza della versione Python, gli argomenti non devono essere interi, anche se i risultati sono più prevedibili se sono dovuti alla precisione in virgola mobile. Se il passaggio è omesso, il suo valore predefinito è 1.

Esempio:

 d3.range(10) // returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

… più portata, usando una funzione generatore.

 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. 

Spero che questo sia utile.

C’è un modulo npm per questo (“bereich” è la parola tedesca per “range”). Utilizza i moderni iteratori di JavaScript, quindi puoi utilizzarlo in vari modi, ad esempio:

 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)) { // ... } 

Supporta anche intervalli decrescenti (semplicemente scambiando min e max ) e supporta anche passi diversi da 1 .

Disclaimer: Sono l’autore di questo modulo, quindi per favore prendi la mia risposta con un pizzico di sale.

Sono stato sorpreso di incontrare questo thread e non vedere nulla come la mia soluzione (forse ho perso una risposta), quindi eccolo qui. Uso una funzione di intervallo semplice nella syntax ES6:

 // [begin, end[ const range = (b, e) => Array.apply(null, Array(e - b)).map((_, i) => {return i+b;}); 

Ma funziona solo quando si conta avanti (cioè inizio

 const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : bi;}); 

Ecco un bel modo breve per farlo in ES6 con solo numeri (non so la sua velocità confronta):

 Array.prototype.map.call(' '.repeat(1 + upper - lower), (v, i) => i + lower) 

Per un intervallo di singoli caratteri, puoi modificarlo leggermente:

 Array.prototype.map.call(' '.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt())); 

Completa l’implementazione di ES6 usando la firma di intervallo ([start,] stop [, passo]):

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

Se si desidera un passaggio negativo automatico, aggiungere

 if(stop 

O più minimalisticamente:

 range=(b, e, step=1)=>{ if(!e){e=b;b=0} return Array.from(new Array(int((eb)/step)), (_,i) => b 

Se hai gamme enormi, guarda l'approccio generatore di Paolo Moretti

Ho trovato una funzione della gamma JS equivalente a quella in PHP, e funziona incredibilmente bene qui . Funziona avanti e indietro, e funziona con numeri interi, float e alfabeti!

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

Ed ecco la versione minificata:

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

Per un approccio più ruby con una buona retrocompatibilità:

range([begin], end = 0) dove begin e end sono numeri

 var range = function(begin, end) { if (typeof end === "undefined") { end = begin; begin = 0; } var result = [], modifier = end > begin ? 1 : -1; for ( var i = 0; i <= Math.abs(end - begin); i++ ) { result.push(begin + i * modifier); } return result; } 

Esempi:

 range(3); //=> [0, 1, 2, 3] range(-2); //=> [0, -1, -2] range(1, 2) //=> [1, 2] range(1, -2); //=> [1, 0, -1, -2]