Есть ли в JavaScript метод типа range () для генерации диапазона в заданных пределах? - PullRequest
653 голосов
/ 09 октября 2010

В PHP вы можете сделать ...

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

То есть есть функция, которая позволяет получить диапазон чисел или символов, передав верхнюю и нижнюю границы.

Есть ли что-нибудь встроенное в JavaScript для этого? Если нет, то как бы я это реализовал?

Ответы [ 50 ]

6 голосов
/ 30 октября 2012

Использование Генераторов гармонии , , поддерживаемых всеми браузерами, кроме 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;
        }
    }
});

Примеры

взять

Пример 1.

take занимает столько, сколько может получить

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

возвращает

[100, 105, 110, 115, 120]

Пример 2.

to необязательно

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

возвращает

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

takeAll

Пример 3.

from необязательно

takeAll( range( {to: 5} ) )

возвращает

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

Пример 4.

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

возвращает

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

Пример 5.

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

возвращает

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

5 голосов
/ 30 ноября 2015

d3 также имеет встроенную функцию диапазона. Смотри https://github.com/mbostock/d3/wiki/Arrays#d3_range:

d3.range ([запуск, остановка [, шаг])

Создает массив, содержащий арифметическую прогрессию, подобный встроенному диапазону Python. Этот метод часто используется для итерации последовательности числовых или целочисленных значений, таких как индексы в массиве. В отличие от версии Python аргументы не обязательно должны быть целыми числами, хотя результаты более предсказуемы, если они обусловлены точностью с плавающей запятой. Если шаг пропущен, по умолчанию он равен 1.

Пример:

d3.range(10)
// returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5 голосов
/ 02 февраля 2015

Вы можете использовать lodash функцию _.range(10) https://lodash.com/docs#range

5 голосов
/ 22 мая 2015

Что касается генерации числового массива для заданного диапазона, я использую это:

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]

Очевидно, он не будет работать для алфавитных массивов.

5 голосов
/ 11 октября 2017

... больше диапазона, используя функцию генератора.

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.

Надеюсь, это полезно.

4 голосов
/ 08 октября 2016

Завершить реализацию ES6, используя подпись диапазона ([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)
}

Если вы хотите автоматический отрицательный шаг, добавьте

if(stop<start)step=-Math.abs(step)

или более минималистично:

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

Если у вас огромные диапазоны, взгляните на подход генератора Паоло Моретти

4 голосов
/ 13 февраля 2018

Для этого есть модуль npm bereich («bereich» - немецкое слово «range»). Он использует современные итераторы JavaScript, поэтому вы можете использовать его различными способами, такими как:

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

Он также поддерживает нисходящие диапазоны (путем простого обмена min и max), а также поддерживает шаги, отличные от 1.

Отказ от ответственности: я являюсь автором этого модуля, поэтому, пожалуйста, примите мой ответ с крошкой соли.

3 голосов
/ 09 октября 2015

Я с удивлением наткнулся на эту ветку и не увидел ничего похожего на мое решение (возможно, я пропустил ответ), так что вот оно Я использую простую функцию диапазона в синтаксисе ES6:

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

Но это работает только при отсчете вперед (т. Е. Begin const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : b-i;});

3 голосов
/ 12 апреля 2019

Этот работает также в обратном порядке.

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 ]
3 голосов
/ 23 июля 2018

Вы также можете сделать следующее:

const range = Array.from(Array(size)).map((el, idx) => idx+1).slice(begin, end);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...