web-dev-qa-db-fra.com

Est-ce que JavaScript a une méthode comme "range ()" pour générer une plage dans les limites fournies?

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?

549
alex

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

63
alex

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)

1124
Ben

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

250
CapK

Voici mes 2 cents:

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

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)
80
Kutyel

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;
};
37
Remi
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']
34
kennebec

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"]
33
Alireza
var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);
23
Artur Klesun

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

  • inclusif - avant range(5,10) // [5, 6, 7, 8, 9, 10]
  • inclusif - en arrière range(10,5) // [10, 9, 8, 7, 6, 5]
  • pas à pas range(10,2,2) // [10, 8, 6, 4, 2]
  • exclusif - forward range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
  • offset - expand range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
  • décalage - rétrécissement range(5,10,0,-2) // [7, 8]
  • step - expand 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
  • Nous commençons par calculer la longueur du tableau de résultats en utilisant (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1) pour le simplifier (différence * offset dans les deux sens/pas)
  • Après avoir obtenu la longueur, nous créons un tableau vide avec les valeurs initialisées en utilisant new Array(length).fill(0);à vérifier ici
  • Nous avons maintenant un tableau [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 versa
  • À chaque itération, startingPoint + stepSize * index nous donnera la valeur dont nous avons besoin
23
azerafati

Le 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 .

16
Mike Dinescu

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 ]
14
c.P.u1

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.

11
Justin

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})}
10
Rick Hitchcock

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]
8
Sasha Zezulinsky

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);
}
8
Hero Qu

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);
}
8
Paolo Moretti

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

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] 
7
user642922

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

Exemples

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

6
Janus Troelsen

vous pouvez utiliser lodash fonction _.range(10)https://lodash.com/docs#range

5
lkan

... 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.

5
John Swindin

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.

5
jhaskell

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]
4
Bob Baxley

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.

4
Golo Roden

range(start,end,step): avec les itérateurs ES6

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

Notes spéciales

4
Evan Carroll

Implé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

4
Anona112

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]);
        })
    })
})
3
Marcel Mandatory

Vous pouvez également faire ce qui suit:

const range = Array.from(Array(size)).map((el, idx) => idx+1).slice(begin, end);
3
gty3310

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

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()));
3
Michael Plautz

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)
2
Marc Sloth Eastman

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 ]
1
Rocco Ghielmini

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']

1
jules3c

Pour une approche plus semblable à Ruby avec une bonne compatibilité ascendante:

range([begin], end = 0)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]
1
Christophe Marois

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 ]
1
Zack

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

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));
1
Rahul Vala

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]
1
Jabba

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

0
Vivek Maru

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

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

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]
0
DMfll

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.

0
mjwrazor

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

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

0
Mohamed Atia

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]
0
Alvin K.

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

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

0
Madbreaks