En PHP, vous pouvez faire ...
range(1, 3); // Array(1, 2, 3)
range("A", "C"); // Array("A", "B", "C")
C'est-à-dire qu'une fonction vous permet d'obtenir une plage de nombres ou de caractères en passant les limites supérieure et inférieure.
Y a-t-il quelque chose d'intégré dans JavaScript nativement pour cela? Sinon, comment pourrais-je le mettre en œuvre?
Cela fonctionne pour les caractères et les nombres, en avant ou en arrière avec une étape optionnelle.
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 vous préférez augmenter les types natifs, affectez-le à 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));
Nombres
[...Array(5).keys()];
=> [0, 1, 2, 3, 4]
Itération du caractère
String.fromCharCode(...[...Array('D'.charCodeAt(0) - 'A'.charCodeAt(0) + 1).keys()].map(i => i + 'A'.charCodeAt(0)));
=> "ABCD"
Itération
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"
En tant que fonctions
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)))
}
Comme fonctions typées
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)))
}
lodash.js _.range()
fonction
_.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"
Anciens navigateurs non es6 sans bibliothèque:
Array.apply(null, Array(5)).map(function (_, i) {return i;});
=> [0, 1, 2, 3, 4]
console.log([...Array(5).keys()]);
Merci.
(crédit ES6 de Nils Petersohn et d'autres commentateurs)
Pour les numéros, vous pouvez utiliser ES6 Array.from()
, qui fonctionne dans tout ce que vous faites maintenant sauf IE:
Version plus courte:
Array.from({length: 20}, (x,i) => i);
Version plus longue:
Array.from(new Array(20), (x,i) => i)
qui crée un tableau de 0 à 19 inclus. Cela peut être réduit à l'une de ces formes:
Array.from(Array(20).keys())
// or
[...Array(20).keys()]
Les limites inférieure et supérieure peuvent également être spécifiées, par exemple:
Array.from(new Array(20), (x,i) => i + *lowerBound*)
Un article décrivant cela plus en détail: http://www.2ality.com/2014/05/es6-array-methods.html
Voici mes 2 cents:
function range(start, count) {
return Array.apply(0, Array(count))
.map(function (element, index) {
return index + start;
});
}
Ma nouvelle forme préférée ( ES2015 )
Array(10).fill(1).map((x, y) => x + y)
Et si vous avez besoin d’une fonction avec un paramètre step
:
const range = (start, stop, step = 1) =>
Array(Math.ceil((stop - start) / step)).fill(start).map((x, y) => x + y * step)
fonction de portée simple:
function range(start, stop, step){
var a=[start], b=start;
while(b<stop){b+=(step || 1);a.Push(b)}
return a;
};
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, en JavaScript, nous n’avons pas de fonction range()
commePHP, nous avons donc besoin de créer cette fonction, ce qui est assez simple, j’écris quelques fonctions d’une ligne pour vous et les sépare les pour les nombres et les alphabets comme ci-dessous:
pour numéros :
function numberRange (start, end) {
return new Array(end - start).fill().map((d, i) => i + start);
}
et appelez comme ça:
numberRange(5, 10); //[5, 6, 7, 8, 9]
pour Alphabets :
function alphabetRange (start, end) {
return new Array(end.charCodeAt(0) - start.charCodeAt(0)).fill().map((d, i) => String.fromCharCode(i + start.charCodeAt(0)));
}
et appelez comme ça:
alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"]
var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);
Fonction pratique pour faire l'affaire, lancez l'extrait de code ci-dessous
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));
voici comment l'utiliser
plage (début, fin, étape = 1, décalage = 0);
range(5,10) // [5, 6, 7, 8, 9, 10]
range(10,5) // [10, 9, 8, 7, 6, 5]
range(10,2,2) // [10, 8, 6, 4, 2]
range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
range(5,10,0,-2) // [7, 8]
range(10,0,2,2) // [12, 10, 8, 6, 4, 2, 0, -2]
j'espère que vous le trouverez utile.
Et voici comment cela fonctionne.
Fondamentalement, je calcule d'abord la longueur du tableau résultant et crée un tableau rempli de zéros à cette longueur, puis le remplis avec les valeurs nécessaires
(step || 1)
=> Et d'autres comme cela signifie utiliser la valeur de step
et si elle n'a pas été fournie, utiliser plutôt 1
(Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1)
pour le simplifier (différence * offset dans les deux sens/pas)new Array(length).fill(0);
à vérifier ici[0,0,0,..]
de la longueur souhaitée. Nous mappons dessus et renvoyons un nouveau tableau avec les valeurs dont nous avons besoin en utilisant Array.map(function() {})
var direction = start < end ? 1 : 0;
Évidemment, si start
n'est pas plus petit que end
, nous devons revenir en arrière. Je veux dire aller de 0 à 5 ou vice versastartingPoint
+ stepSize
* index
nous donnera la valeur dont nous avons besoinLe Javascript standard n'a pas de fonction intégrée pour générer des plages. Plusieurs frameworks javascript prennent en charge de telles fonctionnalités ou, comme d’autres l’ont souligné, vous pouvez toujours utiliser vos propres outils.
Si vous souhaitez vérifier, la ressource définitive est la Norme ECMA-262 .
Utilisation des fonctions opérateur Harmony spread et:
var range = (start, end) => [...Array(end - start + 1)].map((_, i) => start + i);
Exemple:
range(10, 15);
[ 10, 11, 12, 13, 14, 15 ]
Avez-vous effectué des recherches sur diverses fonctions de plage .Vérifiez la comparaison jsperf des différentes façons de réaliser ces fonctions. Certainement pas une liste parfaite ou exhaustive, mais devrait aider :)
Le gagnant est...
function range(lowEnd,highEnd){
var arr = [],
c = highEnd - lowEnd + 1;
while ( c-- ) {
arr[c] = highEnd--
}
return arr;
}
range(0,31);
Techniquement, ce n’est pas le plus rapide sur firefox, mais une différence de vitesse incroyable (à l’ho) sur chrome le compense.
Il est également intéressant de noter à quel point le chrome avec ces fonctions de tableau est plus rapide que Firefox. Chrome est au moins 4 ou 5 fois plus rapide.
Un défi intéressant serait d'écrire la fonction la plus courte pour le faire. Récursion à la rescousse!
function r(a,b){return a>b?[]:[a].concat(r(++a,b))}
Il a tendance à être lent sur de grandes distances, mais heureusement, les ordinateurs quantiques sont tout proches.
Un bonus supplémentaire est que c'est obscurcissant. Parce que nous savons tous combien il est important de cacher notre code aux regards indiscrets.
Pour masquer réellement et complètement la fonction, procédez comme suit:
function r(a,b){return (a<b?[a,b].concat(r(++a,--b)):a>b?[]:[a]).sort(function(a,b){return a-b})}
Je coderais quelque chose comme ça:
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]
Son comportement est similaire à celui de la gamme Python:
>>> range(-4,2)
[-4, -3, -2, -1, 0, 1]
Une autre version utilisant des générateurs ES6 (voir grand Paolo Moretti répond avec des générateurs 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 ]
Ou, si nous avons seulement besoin d'iterable, alors:
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);
}
Vous pouvez utiliser lodash ou Undescore.jsrange
:
var range = require('lodash/range')
range(10)
// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Alternativement, si vous n'avez besoin que d'une plage d'entiers consécutifs, vous pouvez faire quelque chose comme:
Array.apply(undefined, { length: 10 }).map(Number.call, Number)
// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Dans ES6, range
peut être implémenté avec 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;
}
}
Cette implémentation économise de la mémoire lors de l'itération de grandes séquences, car elle ne doit pas matérialiser toutes les valeurs dans un tableau:
for (let i of range(1, oneZillion)) {
console.log(i);
}
Une implémentation plutôt minimaliste qui utilise beaucoup ES6 peut être créée comme suit, en attirant une attention particulière sur la méthode Array.from()
static
const getRange = (start, stop) => Array.from(
new Array((stop - start) + 1),
(_, i) => i + start
);
Bien que ce ne soit pas de PHP, mais une imitation de range
dePython.
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]
Utilisation de générateurs d’harmonie , supporté par tous les navigateurs sauf 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;
}
}
});
prendre
Exemple 1.
take
ne prend que ce qu'il peut obtenir
take(10, range( {from: 100, step: 5, to: 120} ) )
résultats
[100, 105, 110, 115, 120]
Exemple 2.
to
non nécessaire
take(10, range( {from: 100, step: 5} ) )
résultats
[100, 105, 110, 115, 120, 125, 130, 135, 140, 145]
takeAll
Exemple 3.
from
non nécessaire
takeAll( range( {to: 5} ) )
résultats
[0, 1, 2, 3, 4, 5]
Exemple 4.
takeAll( range( {to: 500, step: 100} ) )
résultats
[0, 100, 200, 300, 400, 500]
Exemple 5.
takeAll( range( {from: 'z', to: 'a'} ) )
résultats
["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"]
vous pouvez utiliser lodash
fonction _.range(10)
https://lodash.com/docs#range
... plus de gamme, en utilisant une fonction de générateur.
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.
J'espère que c'est utile.
En ce qui concerne la génération d’un tableau numérique pour une plage donnée, j’utilise ceci:
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]
De toute évidence, cela ne fonctionnera pas pour les tableaux alphabétiques.
d3 a également une fonction de plage intégrée. Voir https://github.com/mbostock/d3/wiki/Arrays#d3_range :
d3.range ([démarrer,] arrêter [ étape])
Génère un tableau contenant une progression arithmétique, similaire à la plage intégrée de Python. Cette méthode est souvent utilisée pour parcourir une séquence de valeurs numériques ou entières, telles que les index dans un tableau. Contrairement à la version Python, les arguments ne doivent pas nécessairement être des entiers, bien que les résultats soient plus prévisibles s'ils sont dus à la précision de la virgule flottante. Si step est omis, la valeur par défaut est 1.
Exemple:
d3.range(10)
// returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Il existe un module npm bereich pour cela ("bereich" est le mot allemand pour "range"). Il utilise les itérateurs de JavaScript modernes, vous pouvez donc l'utiliser de différentes manières, telles que:
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)) {
// ...
}
Il prend également en charge les plages descendantes (en échangeant simplement min
et max
), ainsi que les étapes autres que 1
.
Déni de responsabilité: je suis l'auteur de ce module, veuillez donc prendre ma réponse avec un grain de sel.
range(start,end,step)
: avec les itérateurs ES6Vous ne demandez qu'une limite supérieure et inférieure. Ici nous en créons un avec un pas aussi.
Vous pouvez facilement créer la fonction de générateur range()
qui peut fonctionner comme un itérateur. Cela signifie que vous n'avez pas besoin de pré-générer tout le tableau.
function * range ( start, end, step = 1 ) {
let state = start;
while ( state < end ) {
yield state;
state += step;
}
return;
};
Vous pouvez maintenant créer quelque chose qui pré-génère le tableau à partir de l'itérateur et retourne une liste. Ceci est utile pour les fonctions qui acceptent un tableau. Pour cela, nous pouvons utiliser Array.from()
const generate_array = (start,end,step) =>
Array.from( range(start,end,step) );
Maintenant, vous pouvez facilement générer un tableau statique,
const array1 = generate_array(1,10,2);
const array1 = generate_array(1,7);
Mais quand quelque chose désire un itérateur (ou vous donne la possibilité d'utiliser un itérateur), vous pouvez facilement en créer un aussi.
for ( const i of range(1, Number.MAX_SAFE_INTEGER, 7) ) {
console.log(i)
}
R.range
comme fait LodashImplémentation complète de ES6 à l'aide de la signature de plage ([start,] stop [ step]):
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 vous voulez une progression négative automatique, ajoutez
if(stop<start)step=-Math.abs(step)
Ou de manière plus minimaliste:
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 vous avez d'énormes gammes, regardez l'approche du générateur de Paolo Moretti
Aucun des exemples n’avait de tests, d’implémentation pour étape avec une option pour produire des valeurs décroissantes.
export function range(start = 0, end = 0, step = 1) {
if (start === end || step === 0) {
return [];
}
const diff = Math.abs(end - start);
const length = Math.ceil(diff / step);
return start > end
? Array.from({length}, (value, key) => start - key * step)
: Array.from({length}, (value, key) => start + key * step);
}
Tests:
import range from './range'
describe('Range', () => {
it('default', () => {
expect(range()).toMatchObject([]);
})
it('same values', () => {
expect(range(1,1)).toMatchObject([]);
})
it('step=0', () => {
expect(range(0,1,0)).toMatchObject([]);
})
describe('step=1', () => {
it('normal', () => {
expect(range(6,12)).toMatchObject([6, 7, 8, 9, 10, 11]);
})
it('reversed', () => {
expect(range(12,6)).toMatchObject([12, 11, 10, 9, 8, 7]);
})
})
describe('step=5', () => {
it('start 0 end 60', () => {
expect(range(0, 60, 5)).toMatchObject([0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]);
})
it('reversed start 60 end -1', () => {
expect(range(55, -1, 5)).toMatchObject([55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0]);
})
})
})
Vous pouvez également faire ce qui suit:
const range = Array.from(Array(size)).map((el, idx) => idx+1).slice(begin, end);
J'ai été surpris de tomber sur ce fil et de ne rien voir comme ma solution (peut-être que j'ai raté une réponse), alors la voici ... .. J'utilise une fonction de plage simple dans la syntaxe ES6:
// [begin, end[
const range = (b, e) => Array.apply(null, Array(e - b)).map((_, i) => {return i+b;});
Mais cela ne fonctionne que si vous comptez en avant (ie. Begin <end), nous pouvons donc le modifier légèrement si besoin, comme ceci:
const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : b-i;});
Voici un bon moyen de le faire dans ES6 avec des chiffres uniquement (je ne sais pas si sa vitesse est comparable):
Array.prototype.map.call(' '.repeat(1 + upper - lower), (v, i) => i + lower)
Pour une gamme de caractères simples, vous pouvez le modifier légèrement:
Array.prototype.map.call(' '.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt()));
Mon collègue Codegolfing a proposé ceci (ES6), y compris:
(s,f)=>[...Array(f-s+1)].map((e,i)=>i+s)
non inclus:
(s,f)=>[...Array(f-s)].map((e,i)=>i+s)
Celui-ci fonctionne aussi en sens inverse.
const range = ( a , b ) => Array.from( new Array( b > a ? b - a : a - b ), ( x, i ) => b > a ? i + a : a - i );
range( -3, 2 ); // [ -3, -2, -1, 0, 1 ]
range( 1, -4 ); // [ 1, 0, -1, -2, -3 ]
Il n'y a pas de méthode native. Mais vous pouvez le faire avec la méthode filter
de Array
.
var range = (array, start, end) =>
array.filter((element, index)=>index>=start && index <= end)
alert( range(['a','h','e','l','l','o','s'],1,5) )
// ['h','e','l','l','o']
Pour une approche plus semblable à Ruby avec une bonne compatibilité ascendante:
range([begin], end = 0)
où begin
et end
sont des nombres
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;
}
Exemples:
range(3); //=> [0, 1, 2, 3]
range(-2); //=> [0, -1, -2]
range(1, 2) //=> [1, 2]
range(1, -2); //=> [1, 0, -1, -2]
Une solution récursive pour générer un tableau entier dans les limites.
function intSequence(start, end, n = start, arr = []) {
return (n === end) ? arr.concat(n)
: intSequence(start, end, start < end ? n + 1 : n - 1, arr.concat(n));
}
$> intSequence(1, 1)
<- Array [ 1 ]
$> intSequence(1, 3)
<- Array(3) [ 1, 2, 3 ]
$> intSequence(3, -3)
<- Array(7) [ 3, 2, 1, 0, -1, -2, -3 ]
J'ai trouvé une fonction de gamme JS équivalente à celle de PHP et fonctionne incroyablement bien ici . Fonctionne en avant et en arrière et fonctionne avec des nombres entiers, des flottants et des alphabets!
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;
}
Et voici la version minifiée:
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};
Vous pouvez utiliser les lignes suivantes pour garder les choses simples et courtes
var start = 4;
var end = 20;
console.log(Array(end - start + 1).fill(start).map((x, y) => x + y));
Voici ma solution qui imite Python. En bas, vous trouverez quelques exemples d'utilisation. Cela fonctionne avec les nombres, tout comme range
de Python:
var assert = require('assert'); // if you use Node, otherwise remove the asserts
var L = {}; // L, i.e. 'list'
// range(start, end, step)
L.range = function (a, b, c) {
assert(arguments.length >= 1 && arguments.length <= 3);
if (arguments.length === 3) {
assert(c != 0);
}
var li = [],
i,
start, end, step,
up = true; // Increasing or decreasing order? Default: increasing.
if (arguments.length === 1) {
start = 0;
end = a;
step = 1;
}
if (arguments.length === 2) {
start = a;
end = b;
step = 1;
}
if (arguments.length === 3) {
start = a;
end = b;
step = c;
if (c < 0) {
up = false;
}
}
if (up) {
for (i = start; i < end; i += step) {
li.Push(i);
}
} else {
for (i = start; i > end; i += step) {
li.Push(i);
}
}
return li;
}
Exemples:
// range
L.range(0) -> []
L.range(1) -> [0]
L.range(2) -> [0, 1]
L.range(5) -> [0, 1, 2, 3, 4]
L.range(1, 5) -> [1, 2, 3, 4]
L.range(6, 4) -> []
L.range(-2, 2) -> [-2, -1, 0, 1]
L.range(1, 5, 1) -> [1, 2, 3, 4]
L.range(0, 10, 2) -> [0, 2, 4, 6, 8]
L.range(10, 2, -1) -> [10, 9, 8, 7, 6, 5, 4, 3]
L.range(10, 2, -2) -> [10, 8, 6, 4]
Je préfère le chemin ci-dessous
var range = function(x, y) {
return Array(y - x+1).fill(x).map((a, b) => {return a+b}).filter(i => i >= x);
};
console.log(range(3, 10));
C'est ce que j'utilise pour les plages de nombres:
const rangeFrom0 = end => [...Array(end)].map((_, index) => index);
ou
const rangeExcEnd = (start, step, end) => [...Array(end - start + 1)]
.map((_, index) => index + start)
.filter(x => x % step === start % step);
Solution:
//best performance
var range = function(start, stop, step) {
var a = [start];
while (start < stop) {
start += step || 1;
a.Push(start);
}
return a;
};
//or
var range = function(start, end) {
return Array(++end-start).join(0).split(0).map(function(n, i) {
return i+start
});
}
Voici une définition d'une fonction de plage qui se comporte exactement comme le type range
de Python, sauf que celui-ci n'est pas paresseux. Il devrait être facile de le transformer en générateur.
Les arguments du constructeur d'intervalle doivent être des nombres. Si l'argument step est omis, la valeur par défaut est 1. Si l'argument start est omis, la valeur par défaut est 0. Si step est zéro, une erreur est générée.
range = (start, stop, step=1) => {
if(step === 0) throw new Error("range() arg 3 must not be zero");
const noStart = stop == null;
stop = noStart ? start : stop;
start = noStart ? 0 : start;
const length = Math.ceil(((stop - start) / step));
return Array.from({length}, (_, i) => (i * step) + start);
}
console.log(range(-10, 10, 2));
//output [Array] [-10,-8,-6,-4,-2,0,2,4,6,8]
console.log(range(10));
// [Array] [0,1,2,3,4,5,6,7,8,9]
console.log(3, 12);
// [Array] [3,4,5,6,7,8,9,10,11]
J'aimerais ajouter ce que je pense être une version très ajustable et très rapide.
const range = (start, end) => {
let all = [];
if (typeof start === "string" && typeof end === "string") {
// Return the range of characters using utf-8 least to greatest
const s = start.charCodeAt(0);
const e = end.charCodeAt(0);
for (let i = s; i <= e; i++) {
all.Push(String.fromCharCode(i));
}
} else if (typeof start === "number" && typeof end === "number") {
// Return the range of numbers from least to greatest
for(let i = end; i >= start; i--) {
all.Push(i);
}
} else {
throw new Error("Did not supply matching types number or string.");
}
return all;
}
// usage
const aTod = range("a", "d");
Aussi TypeScript si vous voudriez
const range = (start: string | number, end: string | number): string[] | number[] => {
const all: string[] | number[] = [];
if (typeof start === "string" && typeof end === "string") {
const s: number = start.charCodeAt(0);
const e: number = end.charCodeAt(0);
for (let i = s; i <= e; i++) {
all.Push(String.fromCharCode(i));
}
} else if (typeof start === "number" && typeof end === "number") {
for (let i = end; i >= start; i--) {
all.Push(i);
}
} else {
throw new Error("Did not supply matching types number or string.");
}
return all;
}
// Usage
const negTenToten: number[] = range(-10, 10) as number[];
Fait avec une influence d'autres réponses. L'utilisateur est parti maintenant.
Si nous saisissons quelque chose comme [4, 2]
, nous obtiendrons [2, 3, 4]
en sortie, nous pourrons travailler avec cela.
function createRange(array) {
var range = [];
var highest = array.reduce(function(a, b) {
return Math.max(a, b);
});
var lowest = array.reduce(function(a, b) {
return Math.min(a, b);
});
for (var i = lowest; i <= highest; i++) {
range.Push(i);
}
return range;
}
Voici une approche simple basée sur @benmcdonald et d’autres, plusieurs lignes bien que….
let K = [];
for (i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {
K.Push(String.fromCharCode(i))
};
console.log(K);
Codé selon les spécifications de 2010 (oui, nous sommes en 2016 avec les générateurs ES6). Voici ma prise, avec des options pour émuler la fonction range()
de Python.
Array.range = function(start, end, step){
if (start == undefined) { return [] } // "undefined" check
if ( (step === 0) ) { return []; // vs. throw TypeError("Invalid 'step' input")
} // "step" == 0 check
if (typeof start == 'number') { // number check
if (typeof end == 'undefined') { // single argument input
end = start;
start = 0;
step = 1;
}
if ((!step) || (typeof step != 'number')) {
step = end < start ? -1 : 1;
}
var length = Math.max(Math.ceil((end - start) / step), 0);
var out = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {
out[idx] = start;
}
// Uncomment to check "end" in range() output, non Pythonic
if ( (out[out.length-1] + step) == end ) { // "end" check
out.Push(end)
}
} else {
// Historical: '&' is the 27th letter: http://nowiknow.com/and-the-27th-letter-of-the-alphabet/
// Axiom: 'a' < 'z' and 'z' < 'A'
// note: 'a' > 'A' == true ("small a > big A", try explaining it to a kid! )
var st = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&'; // axiom ordering
if (typeof end == 'undefined') { // single argument input
end = start;
start = 'a';
}
var first = st.indexOf(start);
var last = st.indexOf(end);
if ((!step) || (typeof step != 'number')) {
step = last < first ? -1 : 1;
}
if ((first == -1) || (last == -1 )) { // check 'first' & 'last'
return []
}
var length = Math.max(Math.ceil((last - first) / step), 0);
var out = Array(length);
for (var idx = 0; idx < length; idx++, first += step) {
out[idx] = st[first];
}
// Uncomment to check "end" in range() output, non Pythonic
if ( (st.indexOf(out[out.length-1]) + step ) == last ) { // "end" check
out.Push(end)
}
}
return out;
}
Exemple:
Array.range(5); // [0,1,2,3,4,5]
Array.range(4,-4,-2); // [4, 2, 0, -2, -4]
Array.range('a','d'); // ["a", "b", "c", "d"]
Array.range('B','y'); // ["B", "A", "z", "y"], different from chr() ordering
Array.range('f'); // ["a", "b", "c", "d", "e", "f"]
Array.range(-5); // [], similar to python
Array.range(-5,0) // [-5,-4-,-3-,-2,-1,0]
Ma prise en utilisant des opérateurs ternaires conditionnels dans la boucle for (pas de test d'argument, cependant).
function range(start,end,step){
var resar = [];
for (var i=start;(step<0 ? i>=end:i<=end); i += (step == undefined ? 1:step)){
resar.Push(i);
};
return resar;
};
Pour les lettres, il s’agit d’une simple solution Vanilla JS que j’ai imaginée pour générer des plages de lettres. Il est destiné à générer des tableaux de lettres majuscules ou minuscules, uniquement.
function range(first, last) {
var r = [],
i = first.charCodeAt(0);
while(i <= last.charCodeAt(0)) {
r.Push(String.fromCharCode(i++));
}
return r;
}
console.dir(range("a", "f"));
console.dir(range("G", "Z"));