Existe-t-il une fonction en JavaScript similaire à la fonction range()
de Python?
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;
}
Non, il n'y en a pas, mais vous pouvez en créer un.
range()
de PythonEn essayant de émuler comment cela fonctionne 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.
range()
en JavaScript et PythonCela fonctionne de la manière suivante:
range(4)
renvoie [0, 1, 2, 3]
,range(3,6)
renvoie [3, 4, 5]
,range(0,10,2)
renvoie [0, 2, 4, 6, 8]
,range(10,0,-1)
renvoie [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
,range(8,2,-2)
renvoie [8, 6, 4]
,range(8,2)
renvoie []
,range(8,2,2)
renvoie []
,range(1,5,-1)
renvoie []
,range(1,5,-2)
renvoie []
,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 qui fonctionne de la même manière que la fonction range()
de Python, vous pouvez utiliser la solution susmentionnée.
Pour une gamme très simple dans ES6:
let range = n => Array.from(Array(n).keys())
2018: cette réponse ne cesse de recevoir des votes, voici donc une mise à jour. Le code ci-dessous est obsolète, mais heureusement, les générateurs standardisés ES6 et le mot clé yield
sont universellement pris en charge sur toutes les plates-formes. Un exemple de range()
paresseux utilisant yield
peut être trouvé ici .
En plus de ce qui a déjà été dit, Javascript 1.7+ prend en charge 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
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
Un port de la fonction range
de Python est fourni par les bibliothèques d’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);
=> []
En fusionnant les deux réponses de @Tadeck et @georg , j'ai trouvé ceci
function* range(start, stop, step = 1) {
if (typeof stop === 'undefined') {
// 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 de ES6/JS1.7:
for (let i of range(0, 10, 2)) {
console.log(i);
}
// Outputs => 0 2 4 6 8
Peut être obtenu en attachant un itérateur au prototype Number
Number.prototype[Symbol.iterator] = function* () {
for (var i = 0; i <= this; i++) {
yield i
}
}
[...5] // will result in [0,1,2,3,4,5]
Extrait du cours de Kyle Simpson Repenser le JavaScript asynchrone
Voici.
Ceci é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 numéro, 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]
Pour obtenir un tableau de taille x
, voici un one-liner sans utiliser aucune bibliothèque
var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
travailler en tant que
> range(4)
[0, 1, 2, 3]
Voici une petite extension pour l'une des réponses au cas où vous auriez besoin de spécifier les positions de début et de fin de la plage:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
Ce 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 supporte tous les arguments qui peuvent être comparés à 0
et stop
et peuvent être incrémentés de step
. Il se comporte de manière identique à la version Python lorsqu'il est utilisé avec des nombres ne dépassant pas Number.MAX_SAFE_INTEGER
.
Veuillez noter les cas 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's , @ Volv's et @ janka102's answer qui renvoie []
, undefined
ou entre une boucle infinie lorsque step
est évalué à 0
ou NaN
, cette fonction de générateur génère une exception similaire Le comportement de Python.
Raffiné davantage avec les paramètres par défaut de l’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
}
Vous pouvez utiliser underscore library. Il contient des dizaines de fonctions utiles pour travailler avec des tableaux et bien d’autres.
MDN recommande cette approche: Générateur de séquence (plage)
Non, il n'y en a pas, mais vous pouvez en créer un.
Je suis partial au comportement de gamme de Python3. Vous trouverez ci-dessous l'implémentation par JavaScript de la gamme 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.
Pythonic
imite le comportement Python range
de la meilleure façon possible en utilisant les générateurs de JS (yield
), prenant en charge les cas d'utilisation range(stop)
et range(start, stop, step)
. De plus, la fonction Pythonic
de range
renvoie un objet Generator
construit sur mesure qui prend en charge map
et filter
, de sorte que vous pouvez utiliser des lignes simples telles que:
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
Voici le code dans Pythonic
pour range:
function range(...args) {
if (args.length < 2) {
return new Generator(rangeGeneratorWithStop(...args));
}
return new Generator(rangeGeneratorWithSartAndStopAndStep(...args));
}
const rangeGeneratorWithStop = stop => function * () {
for (let i = 0; i < stop; i++) {
yield i;
}
};
const rangeGeneratorWithSartAndStopAndStep = (start, stop, step = 1) => function * () {
for (let i = start; i < stop; i += step) {
yield i;
}
};
function range(...args) {
if (args.length < 2) {
return new Generator(rangeGeneratorWithStop(...args));
}
return new Generator(rangeGeneratorWithSartAndStopAndStep(...args));
}
class Generator {
constructor(generatorFn) {
this[Symbol.iterator] = generatorFn;
}
map(callbackFn) {
const result = [];
for (const element of this) {
result.Push(callbackFn(element));
}
return result;
}
filter(callbackFn) {
const result = [];
for (const element of this) {
if (callbackFn(element)) {
result.Push(element);
}
}
return result;
}
toArray() {
return Array.from(this);
}
}
Voici une autre implémentation es6
de la plage
// 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}`)
}