Existe-t-il une fonction en JavaScript similaire à celle de Python range()
?
Je pense qu'il devrait y avoir un meilleur moyen que d'écrire les lignes suivantes à chaque fois:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
javascript
python
Clwen
la source
la source
range()
fonctionnement de Python, vous pouvez donc l'utiliser. Il n'existe pas de fonction de ce type dans JavaScript, mais il existe des plugins pour différents frameworks, tels que laRange
classe pour MooTools .Réponses:
Non , il n'y en a pas, mais vous pouvez en créer un .
L'implémentation JavaScript de Python
range()
En essayant d' émuler son fonctionnement en Python , je créerais une fonction similaire à celle-ci:
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; };
Voir ce jsfiddle pour une preuve.
Comparaison entre
range()
JavaScript et PythonCela fonctionne de la manière suivante:
range(4)
retourne[0, 1, 2, 3]
,range(3,6)
retourne[3, 4, 5]
,range(0,10,2)
retourne[0, 2, 4, 6, 8]
,range(10,0,-1)
retourne[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
,range(8,2,-2)
retourne[8, 6, 4]
,range(8,2)
retourne[]
,range(8,2,2)
retourne[]
,range(1,5,-1)
retourne[]
,range(1,5,-2)
retourne[]
,et son homologue Python fonctionne exactement de la même manière (au moins dans les cas mentionnés):
>>> 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) []
Donc, si vous avez besoin d'une fonction pour fonctionner de la même manière que Python
range()
, vous pouvez utiliser la solution mentionnée ci-dessus.la source
stop
c'est supérieur àstart
(et échangez-les sinon).start >= stop
conduire à un tableau vide est nécessaire si l'objectif est vraiment d'émuler la plage de Python. Et je dirais que c'est de toute façon plus intuitif.start >= stop
ne suffit pas pour que cette fonction se comporte commerange()
en Python. J'ai mis à jour ma réponse.Pour une gamme très simple en ES6:
let range = n => Array.from(Array(n).keys())
D' après le commentaire de bigOmega , cela peut être raccourci en utilisant la syntaxe Spread :
let range = n => [...Array(n).keys()]
la source
let range = n => [...Array(n).keys()]
const
autant que possible, mais ici ce sera juste une référence au tableau, donc le tableau serait toujours modifiable: 'Dconst
s'appliquerait à la fonction elle-même, pas à sa valeur de retour. Vous ne souhaitez probablement pas modifier la fonction de quelque manière que ce soit.2018: cette réponse continue de recevoir des votes positifs, voici donc une mise à jour. Le code ci-dessous est obsolète, mais heureusement, les générateurs standardisés ES6 et le
yield
mot - clé, et ils sont universellement pris en charge sur toutes les plates-formes. Un exemple d'range()
utilisation paresseuseyield
peut être trouvé ici .En plus de ce qui a déjà été dit, Javascript 1.7+ fournit un support pour les itérateurs et les générateurs qui peuvent être utilisés pour créer une version paresseuse et économe en mémoire de
range
, similaire àxrange
dans 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
la source
step
argument et le tester sur les valeurs de ma réponse ? Votre réponse est excellente pour les applications pour lesquelles nous avons à l'esprit des navigateurs très spécifiques (cela ne fonctionnera pas dans les versions Google Chrome, Safari et IE antérieures à la 9: stackoverflow.com/a/2209743/548696 ).range
a la "dernière" valeur exclue (il faut donc l'utiliser à la>=
place du>
code ci-dessus)En fusionnant les deux réponses de @Tadeck et @georg , j'ai trouvé ceci:
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; } }
Pour l'utiliser dans une boucle for, vous avez besoin de la boucle for-of 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
la source
step
paramètre, mais quandstop
n'est pas passé, les deuxstart
etstop
doivent être modifiés. Je vais le mettre à jourUn portage de la
range
fonction à partir de Python 2 est fourni par les bibliothèques utilitaires underscore.js et lodash (avec de nombreux autres outils utiles). Exemples copiés à partir des documents de soulignement:_.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); => []
la source
Peut être réalisé en attachant un itérateur au
Number
prototypeNumber.prototype[Symbol.iterator] = function* () { for (var i = 0; i <= this; i++) { yield i } } [...5] // will result in [0,1,2,3,4,5]
Tiré du cours de Kyle Simpson Rethinking Asynchronous JavaScript
la source
Voici une petite extension pour l'une des réponses au cas où vous auriez besoin de spécifier à la fois la position de début et de fin de la plage:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
la source
Voici.
Cela écrira (ou écrasera) la valeur de chaque index avec le numéro d'index.
Array.prototype.writeIndices = function( n ) { for( var i = 0; i < (n || this.length); ++i ) this[i] = i; return this; };
Si vous ne fournissez pas de nombre, il utilisera la longueur actuelle du tableau.
Utilisez-le comme ceci:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
la source
Pour obtenir un tableau de taille
x
, voici un one-liner sans utiliser aucune bibliothèquevar range = n => Array(n + 1).join(1).split('').map((x, i) => i)
travailler en tant que
> range(4) [0, 1, 2, 3]
la source
var range = n => Array(n).fill().map((e, i) => i);
x
» quand vous l'avez réellement utilisén
comme nom de paramètreCe qui suit est une adaptation naturelle de la fonction range () de Python à 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]
Il prend en charge tout argument qui peut être comparé à
0
etstop
et qui peut être incrémenté destep
. Il se comporte de la même manière que la version Python lorsqu'il est utilisé avec des nombres ne dépassant pasNumber.MAX_SAFE_INTEGER
.Veuillez noter les cas d'angle suivants:
[...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
Contrairement à @ Tadeck de , @ de Volv et de @ janka102 réponse qui retour
[]
,undefined
ou entrer dans une boucle infinie lorsquestep
evalue à0
ouNaN
, cette fonction de générateur renvoie une exception similaire au comportement de Python.la source
Plus raffiné avec les paramètres par défaut 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 }
la source
pythonic
imite aurange
mieux le comportement Python en utilisant les générateurs de JS (yield
), prenant en charge à la fois les cas d'utilisationrange(stop)
etrange(start, stop, step)
. De plus,pythonic
larange
fonction de retourne unIterator
objet similaire à Python qui prend en chargemap
etfilter
, donc on pourrait faire des one-liners sophistiqués comme:import {range} from 'pythonic'; // ... const results = range(5).map(wouldBeInvokedFiveTimes); // `results` is now an array containing elements from // 5 calls to wouldBeInvokedFiveTimes
Installez en utilisant
npm
:npm install --save pythonic
Divulgation Je suis l'auteur et le mainteneur de Pythonic
la source
MDN recommande cette approche: Générateur de séquence (plage)
// 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"]
la source
Vous pouvez utiliser la bibliothèque de soulignement . Il contient des dizaines de fonctions utiles pour travailler avec des tableaux et bien d'autres.
la source
Toutes les solutions ici font référence à la gamme de Python 2 (probablement à cause de l'exemple de code que vous avez donné). Cependant, dans Python 3, la méthode range () retourne un itérateur. JavaScript a également des itérateurs et ils sont plus efficaces en termes d'espace que de générer l'ensemble du tableau et de le stocker en mémoire.
La représentation la plus précise de la
range(n)
fonction de Python 3 est doncArray(n).keys()
.Par exemple:
for (let i of Array(n).keys()) { console.log(i) // 0, 1, 2, 3, ..., n }
Un autre exemple (qui a déjà été traité dans les autres réponses). Conversion de l'itérateur en tableau (ES6):
let ary = [...Array(n).keys()]; // ary = [0, 1, 2, 3, ..., n]
la source
Toujours pas de fonction intégrée équivalente à
range()
, mais avec la version la plus récente - ES2015 - vous pouvez créer votre propre implémentation. En voici une version limitée. Limité car il ne prend pas en compte le paramètre step. Juste min, max.const range = (min = null, max = null) => Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
Ceci est accompli par la
Array.from
méthode capable de créer un tableau à partir de n'importe quel objet possédant unelength
propriété. Donc, passer un objet simple avec juste lalength
propriété créera un ArrayIterator qui produira lelength
nombre d'objets.la source
C'est ma manière préférée. Il vous permet de spécifier une ou deux entrées comme en Python.
function range(start, end) { return Array.from(Array(end||start).keys()).slice(!!end*start) }
la source
Voici une autre
es6
implémentation de la gamme// 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}`) }
la source
-20
à-30
?Non, il n'y en a pas, mais vous pouvez en créer un.
Je suis partial pour le comportement de la plage Python3. Vous trouverez ci-dessous l'implémentation JavaScript de la gamme 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.
la source
En supposant que vous ayez besoin d'une gamme simple en une seule étape:
let range = (start, end)=> { if(start === end) return [start]; return [start, ...range(start + 1, end)]; }
autre
let range = (start, end, step)=> { if(start === end) return [start]; return [start, ...range(start + step, end)]; }
reportez-vous ici pour en savoir plus.
la source
Comme répondu précédemment: non , il n'y en a pas. Mais vous pouvez créer le vôtre. Je pense que c'est une approche intéressante pour ES6. Cela fonctionne très similaire à Python 2.7
range()
, mais c'est beaucoup plus dynamique.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 }
Cette fonction peut se comporter de trois manières différentes (tout comme le range () de Python):
range(stop)
range(start, stop)
range(start, stop, step)
Ces exemples:
console.log(range(5)) console.log(range(-2, 2)) console.log(range(2, -2)) console.log(range(10, 20, 2))
Vous donnera la sortie suivante:
[ 0, 1, 2, 3, 4 ] [ -2, -1, 0, 1, 2 ] [ 2, 1, 0, -1, -2 ] [ 10, 12, 14, 16, 18, 20 ]
Notez qu'au lieu d'itérer sur le tableau avec l'
in
opérateur (comme python), vous devez utiliserof
. Ainsi, lai
variable prend la valeur, et non l'index, de l'élément du tableau.for(let i of range(5)) { // do something with i... }
la source
Une option pour NodeJs est d'utiliser un tampon:
[...Buffer.alloc(5).keys()] // [ 0, 1, 2, 3, 4 ]
Ce qui est bien, c'est que vous pouvez itérer directement sur le tampon:
Buffer.alloc(5).forEach((_, index) => console.log(index)) // 0 // 1 // 2 // 3 // 4
Vous ne pouvez pas faire cela avec un tableau non initialisé:
Array(5).forEach((_, index) => console.log(index)) // undefined
Mais, qui dans leur bon esprit utilise un tampon dans un but comme celui-ci;)
la source
Voici comment je fais
let n = 5 [...Array(n).keys()].map(x=>{console.log(x)})
production
0 1 2 3 4
la source