Функция JavaScript похожа на диапазон Python () - PullRequest
72 голосов
/ 25 ноября 2011

Есть ли в JavaScript функция, похожая на Python range()?

Я думаю, что должен быть лучший способ, чем каждый раз писать следующие строки:

array = new Array();
for (i = 0; i < specified_len; i++) {
    array[i] = i;
}

Ответы [ 17 ]

85 голосов
/ 23 июня 2016

Для очень простого диапазона в ES6:

let range = n => Array.from(Array(n).keys())
72 голосов
/ 25 ноября 2011

Нет , его нет, но вы можете сделать один .

Реализация JavaScript Python's range()

Пытаясь эмулировать, как это работает в Python , я бы создал функцию, подобную этой:

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

См. этот jsfiddle для доказательства.

Сравнение range() в JavaScript и Python

Работает следующим образом:

  • 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) возвращает [],

и его аналог Python работают точно так же (по крайней мере, в упомянутых случаях):

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

Так что если вам нужна функция, работающая аналогично range() в Python, вы можете использовать вышеупомянутое решение.

26 голосов
/ 26 ноября 2011

2018: этот ответ продолжает получать положительные отзывы, так что вот обновление. Приведенный ниже код устарел, но, к счастью, стандартизированные генераторы ES6 и ключевое слово yield поддерживаются всеми платформами. Пример ленивого range() с использованием yield можно найти здесь .


В дополнение к тому, что уже было сказано, Javascript 1.7+ обеспечивает поддержку итераторов и генераторов , которые можно использовать для создания ленивой, эффективной для памяти версии range, аналогичной xrange в 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
17 голосов
/ 30 августа 2014

Порт функции Python range предоставляется служебными библиотеками underscore.js и lodash (наряду со многими другими полезными инструментами). Примеры, скопированные из документов с подчеркиванием:

_.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);
=> []
15 голосов
/ 24 октября 2014

Объединяя оба ответа из @ Tadeck и @ georg , я придумал следующее:

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

Чтобы использовать его в цикле for, вам нужноцикл for ES6 / JS1.7:

for (let i of range(0, 10, 2)) {
    console.log(i);
}
// Outputs => 0 2 4 6 8
12 голосов
/ 14 августа 2017

Может быть достигнуто путем присоединения итератора к прототипу 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]

Взято из курса Кайла Симпсона Переосмысление асинхронного JavaScript

7 голосов
/ 25 ноября 2011

Вот, пожалуйста.

Это запишет (или перезапишет) значение каждого индекса с номером индекса.

Array.prototype.writeIndices = function( n ) {
    for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
    return this;
};

Если вы не предоставите число, оно будетиспользуйте текущую длину массива.

Используйте это так:

var array = [].writeIndices(10);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5 голосов
/ 27 марта 2017

Ниже приведена естественная адаптация функции Python range () к 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]

Поддерживается любой аргумент, который можно сравнить с 0 и stop и который можно увеличить на step.Он ведет себя идентично версии Python, когда используется с числами, не превышающими Number.MAX_SAFE_INTEGER.

Обратите внимание на следующие угловые случаи:

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

В отличие от @ Tadeck's , @ Volv's и @ janka102's ответ, который возвращает [], undefined или входит в бесконечный цикл, когда step оценивается как 0 или NaN, эта функция генераторагенерирует исключение, подобное поведению Python.

5 голосов
/ 20 декабря 2016

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

let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
4 голосов
/ 23 марта 2016

Для получения массива размером x, вот одна строка без использования какой-либо библиотеки

var range = n => Array(n + 1).join(1).split('').map((x, i) => i)

работает как

> range(4)
[0, 1, 2, 3]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...