Функция 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); } }