Функция JavaScript, похожая на диапазон Python()
есть ли функция в JavaScript, похожая на Python range()
?
Я думаю, что там должен быть лучший способ, чем писать следующие строки каждый раз:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
15 ответов:
нет, нет, но вы можете сделать один.
реализация JavaScript в Python
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) []
так что если вам нужна функция, чтобы работать так же в Python
range()
, вы можете использовать вышеуказанные решения.
2018: этот ответ продолжает получать upvotes, так что вот обновление. Приведенный ниже код устарел, но, к счастью, ES6 стандартизированные генераторы и
yield
ключевое слово, и они повсеместно поддерживаются на разных платформах. Пример ленивогоrange()
используяyield
можно найти здесь.
В дополнение к тому, что уже сказано, Javascript 1.7+ обеспечивает поддержку итераторы и генераторы который может быть использован для создания ленивого, эффективной памяти версия
range
, simlar toxrange
в 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
сплавляя вместе оба ответа от @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, вам нужен цикл ES6/JS1.7 for-of:
for (let i of range(0, 10, 2)) { console.log(i); } // Outputs => 0 2 4 6 8
может быть достигнуто путем присоединения итератор на
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
вот так.
это будет записывать (или перезаписывать) значение каждого индекса с номером индекса.
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]
для получения массива размере
x
, вот один-лайнер без использования библиотекиvar range = n => Array(n + 1).join(1).split('').map((x, i) => i)
работает в качестве
> range(4) [0, 1, 2, 3]
ниже приводится естественная адаптация питона 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
в отличие от @Тадек это, @Волв это и @janka102 это ответ, который возвращает
[]
,undefined
или введите бесконечный цикл, когдаstep
оценивает в0
илиNaN
, эта функция генератора создает исключение, подобное поведению Python.
вы можете использовать подчеркивание библиотека. Он содержит десятки полезных функций для работы с массивами и многое другое.
дополнительно уточнено с параметрами по умолчанию 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 }
вот небольшое расширение для одного из ответов в случае, если вам нужно указать как начальную, так и конечную позицию диапазона:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
по-прежнему нет встроенной функции, эквивалентной
range()
, но с последней версией - ES2015 - вы можете построить свою собственную реализацию. Вот его ограниченная версия. Ограничено, потому что он не учитывает параметр step. Только мин, макс.
const range = (min = null, max = null) => Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
это достигается с помощью
Array.from
метод, способный построить массив из любого объекта, который имеетlength
собственность. Таким образом, переходя в простой объект только сlength
свойство создаст ArrayIterator, что дастlength
количество объектов.
вот еще
es6
реализация комплекса// 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}`) }
pythonic
имитирует питонаrange
поведение лучше всего он может использовать генераторы JS (yield
), поддерживающей какrange(stop)
иrange(start, stop, step)
варианты использования. Кроме того,pythonic
' srange
функция возвращает custom builtGenerator
объект, который поддерживаетmap
иfilter
, так что можно было бы сделать фантазии однострочные, как:import {range} from 'pythonic'; // ... const results = range(5).map(wouldBeInvokedFiveTimes); // `results` is now an array containing elements from // 5 calls to wouldBeInvokedFiveTimes
установить с помощью
npm
:npm install --save pythonic
здесь код
pythonic
для: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); } }