Есть ли в JavaScript функция, аналогичная Python range()
?
Думаю, должен быть способ лучше, чем каждый раз писать следующие строки:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
javascript
python
Clwen
источник
источник
range()
работы в Python, чтобы вы могли ее использовать. В JavaScript такой функции нет, но есть плагины для разных фреймворков, например,Range
класс для MooTools .Ответы:
Нет , его нет, но сделать можно .
Реализация Python в JavaScript
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()
, вы можете использовать вышеупомянутое решение.источник
stop
оно большеstart
(и поменяйте их местами, если нет).start >= stop
к пустому массиву необходимо, если цель действительно имитировать диапазон Python. И я бы сказал, что в любом случае это более интуитивно понятно.start >= stop
функции недостаточно, чтобы она работала какrange()
в Python. Я обновил свой ответ.Для очень простого диапазона в ES6:
let range = n => Array.from(Array(n).keys())
Из комментария bigOmega , это можно сократить, используя синтаксис Spread :
let range = n => [...Array(n).keys()]
источник
let range = n => [...Array(n).keys()]
const
как можно больше, но здесь это будет просто ссылка на массив, поэтому массив все равно будет редактируемым: 'Dconst
будет применяться к самой функции, а не к ее возвращаемому значению. Вероятно, вы не хотите каким-либо образом изменять функцию.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
источник
step
аргумент и проверить его на значениях из моего ответа ? Ваш ответ отлично подходит для приложений, для которых у нас есть очень специфические браузеры (он не будет работать в Google Chrome, Safari и версии IE до 9: stackoverflow.com/a/2209743/548696 ).range
"последнее" значение (поэтому его нужно использовать вместо в приведенном выше коде)>=
>
Объединив оба ответа от @Tadeck и @georg , я пришел к следующему:
function* range(start, stop, step = 1) { if (stop == null) { // one param defined stop = start; start = 0; } for (let i = start; step > 0 ? i < stop : i > stop; i += step) { yield i; } }
Чтобы использовать его в цикле for, вам понадобится цикл for-of в ES6 / JS1.7:
for (let i of range(5)) { console.log(i); } // Outputs => 0 1 2 3 4 for (let i of range(0, 10, 2)) { console.log(i); } // Outputs => 0 2 4 6 8 for (let i of range(10, 0, -2)) { console.log(i); } // Outputs => 10 8 6 4 2
источник
step
параметра, но еслиstop
он не передан, обаstart
иstop
должны быть изменены. Я буду обновлять егоПорт
range
функции из Python 2 предоставляется служебными библиотеками 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); => []
источник
Может быть достигнуто путем присоединения итератора к
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».
источник
Вот небольшое расширение для одного из ответов на случай, если вам нужно указать как начальную, так и конечную позицию диапазона:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
источник
Ну вот.
Это запишет (или перезапишет) значение каждого индекса с номером индекса.
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]
источник
var range = n => Array(n).fill().map((e, i) => i);
x
», когда вы на самом деле использовали вn
качестве имени параметраНиже приводится естественная адаптация функции 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 - х , @ Volv - х и @ 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 }
источник
pythonic
range
Лучше всего имитирует поведение Python, используя JS 'generators (yield
), поддерживая как варианты использования , такrange(stop)
иrange(start, stop, step)
варианты использования. Кроме того,pythonic
«srange
функция возвращаетIterator
объект , похожий на Python , который поддерживает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
источник
MDN рекомендует этот подход: Генератор последовательности (диапазон)
// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc) const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step)); // Generate numbers range 0..4 console.log("range(0, 4, 1):", range(0, 4, 1)); // [0, 1, 2, 3, 4] // Generate numbers range 1..10 with step of 2 console.log("\nrange(1, 10, 2):", range(1, 10, 2)); // [1, 3, 5, 7, 9] // Generate the alphabet using Array.from making use of it being ordered as a sequence console.log("\nrange('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))", range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))); // ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
источник
Вы можете использовать библиотеку подчеркивания . Он содержит десятки полезных функций для работы с массивами и многое другое.
источник
Все решения здесь относятся к диапазону Python 2 (вероятно, из-за приведенного вами примера кода). Однако в Python 3 метод range () возвращает итератор. В JavaScript также есть итераторы, и они занимают больше места, чем создание всего массива и сохранение его в памяти.
Таким образом, более точное представление о Python 3 в
range(n)
функцииArray(n).keys()
.Например:
for (let i of Array(n).keys()) { console.log(i) // 0, 1, 2, 3, ..., n }
Еще один пример (который уже был рассмотрен в других ответах). Преобразование итератора в массив (ES6):
let ary = [...Array(n).keys()]; // ary = [0, 1, 2, 3, ..., n]
источник
По-прежнему нет встроенной функции, эквивалентной
range()
, но с самой последней версией - ES2015 - вы можете создать свою собственную реализацию. Вот его ограниченная версия. Ограничено, потому что не учитывается параметр шага. Просто мин, макс.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
количество объектов.источник
Это мой предпочтительный способ. Он позволяет вам указать один или два входа, как в Python.
function range(start, end) { return Array.from(Array(end||start).keys()).slice(!!end*start) }
источник
Вот еще одна
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}`) }
источник
-20
до-30
?Нет, его нет, но сделать можно.
Я неравнодушен к поведению диапазона Python3. Ниже вы найдете реализацию Python range () в JavaScript:
function* range(start=0, end=undefined, step=1) { if(arguments.length === 1) {end = start, start = 0} [...arguments].forEach(arg => { if( typeof arg !== 'number') {throw new TypeError("Invalid argument")} }) if(arguments.length === 0) {throw new TypeError("More arguments neede")} if(start >= end) return yield start yield* range(start + step, end, step) } // Use Cases console.log([...range(5)]) console.log([...range(2, 5)]) console.log([...range(2, 5, 2)]) console.log([...range(2,3)]) // You can, of course, iterate through the range instance.
источник
Предполагая, что вам нужен простой диапазон с одним шагом:
let range = (start, end)=> { if(start === end) return [start]; return [start, ...range(start + 1, end)]; }
еще
let range = (start, end, step)=> { if(start === end) return [start]; return [start, ...range(start + step, end)]; }
см. здесь для получения дополнительной информации.
источник
Как ответили ранее: нет , нет. Но вы можете сделать свой собственный. Я считаю, что это интересный подход для ES6. Он работает очень похоже на Python 2.7
range()
, но намного более динамичен.function range(start, stop, step = 1) { // This will make the function behave as range(stop) if(arguments.length === 1) { return [...Array(arguments[0]).keys()] } // Adjusts step to go towards the stop value if((start > stop && !(step < 0)) || (start < stop && !(step > 0))) { step *= -1 } let returnArray = [] // Checks if i is in the interval between start and stop no matter if stop // is lower than start or vice-versa for(let i = start; (i-start)*(i-stop) <= 0; i += step) { returnArray.push(i) } return returnArray }
Эта функция может вести себя тремя разными способами (точно так же, как Python range ()):
range(stop)
range(start, stop)
range(start, stop, step)
Эти примеры:
console.log(range(5)) console.log(range(-2, 2)) console.log(range(2, -2)) console.log(range(10, 20, 2))
Вы получите следующий результат:
[ 0, 1, 2, 3, 4 ] [ -2, -1, 0, 1, 2 ] [ 2, 1, 0, -1, -2 ] [ 10, 12, 14, 16, 18, 20 ]
Обратите внимание, что вместо перебора массива с помощью
in
оператора (например, python) вы должны использоватьof
. Таким образом,i
переменная принимает значение, а не индекс элемента массива.for(let i of range(5)) { // do something with i... }
источник
Вариант для NodeJs - использовать буфер:
[...Buffer.alloc(5).keys()] // [ 0, 1, 2, 3, 4 ]
Что приятно, так это то, что вы можете выполнять итерацию прямо в буфере:
Buffer.alloc(5).forEach((_, index) => console.log(index)) // 0 // 1 // 2 // 3 // 4
Вы не можете сделать это с неинициализированным массивом:
Array(5).forEach((_, index) => console.log(index)) // undefined
Но кто в здравом уме использует буфер для такой цели;)
источник
Вот как я это делаю
let n = 5 [...Array(n).keys()].map(x=>{console.log(x)})
выход
0 1 2 3 4
источник