Existe uma função em JavaScript semelhante à do Python range()
?
Acho que deveria haver uma maneira melhor do que escrever as seguintes linhas todas as vezes:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
javascript
python
Clwen
fonte
fonte
range()
funciona em Python, para que você possa usá-la. Não existe tal função em JavaScript, mas existem alguns plug-ins para diferentes estruturas, comoRange
classe para MooTools .Respostas:
Não , não há nenhum, mas você pode fazer um .
Implementação de JavaScript de Python
range()
Tentando emular como funciona em Python , eu criaria uma função semelhante a esta:
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; };
Veja este jsfiddle para uma prova.
Comparação entre
range()
em JavaScript e PythonFunciona da seguinte maneira:
range(4)
retorna[0, 1, 2, 3]
,range(3,6)
retorna[3, 4, 5]
,range(0,10,2)
retorna[0, 2, 4, 6, 8]
,range(10,0,-1)
retorna[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
,range(8,2,-2)
retorna[8, 6, 4]
,range(8,2)
retorna[]
,range(8,2,2)
retorna[]
,range(1,5,-1)
retorna[]
,range(1,5,-2)
retorna[]
,e sua contraparte Python funciona exatamente da mesma maneira (pelo menos nos casos mencionados):
>>> 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) []
Portanto, se você precisa de uma função para funcionar de forma semelhante à do Python
range()
, pode usar a solução mencionada acima.fonte
stop
seja maior questart
(e troque-os se não).start >= stop
conduzir a um array vazio é necessário se o objetivo for realmente emular o intervalo do Python. E eu diria que é mais intuitivo de qualquer maneira.start >= stop
não é suficiente para esta função se comportar comorange()
em Python. Eu atualizei minha resposta.Para um intervalo muito simples em ES6:
let range = n => Array.from(Array(n).keys())
A partir do comentário de bigOmega , isso pode ser reduzido usando a sintaxe Spread :
let range = n => [...Array(n).keys()]
fonte
let range = n => [...Array(n).keys()]
const
o máximo possível, mas aqui será apenas uma referência ao array, então o array ainda seria editável: 'Dconst
se aplicaria à própria função, não ao seu valor de retorno. Você provavelmente não deseja modificar a função de forma alguma.2018: esta resposta continua recebendo votos positivos, então aqui está uma atualização. O código abaixo está obsoleto, mas felizmente ES6 padronizou geradores e a
yield
palavra - chave, e eles são universalmente suportados em todas as plataformas. Um exemplo derange()
uso preguiçosoyield
pode ser encontrado aqui .Além do que já foi dito, o Javascript 1.7+ fornece suporte para iteradores e geradores que podem ser usados para criar uma versão preguiçosa e com uso eficiente de memória
range
, semelhante aoxrange
do 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
fonte
step
argumento e testá-lo nos valores de minha resposta ? Sua resposta é ótima para os aplicativos para os quais temos navegadores muito específicos em mente (não funciona no Google Chrome, Safari e versão do IE anteriores à 9: stackoverflow.com/a/2209743/548696 ).range
tem o valor "último" excluído (portanto, é necessário usar em>=
vez do>
código acima)Combinando as respostas de @Tadeck e @georg , eu vim com o seguinte:
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; } }
Para usá-lo em um loop for, você precisa do loop 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
fonte
step
parâmetro, mas quandostop
não é passado, ambosstart
estop
precisam ser alterados. Vou atualizá-loUma porta da
range
função do Python 2 é fornecida pelas bibliotecas de utilitários underscore.js e lodash (junto com muitas outras ferramentas úteis). Exemplos copiados dos documentos de sublinhado:_.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); => []
fonte
Pode ser alcançado anexando um iterador ao
Number
protótipoNumber.prototype[Symbol.iterator] = function* () { for (var i = 0; i <= this; i++) { yield i } } [...5] // will result in [0,1,2,3,4,5]
Retirado do curso de Kyle Simpson Rethinking Asynchronous JavaScript
fonte
Aqui está uma pequena extensão para uma das respostas, caso você precise especificar as posições inicial e final do intervalo:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
fonte
Aqui está.
Isso gravará (ou substituirá) o valor de cada índice com o número do índice.
Array.prototype.writeIndices = function( n ) { for( var i = 0; i < (n || this.length); ++i ) this[i] = i; return this; };
Se você não fornecer um número, ele usará o comprimento atual do Array.
Use-o assim:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
fonte
Mais refinado com os parâmetros padrão do 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 }
fonte
Para obter um array de tamanho
x
, aqui está um one-liner sem usar qualquer bibliotecavar range = n => Array(n + 1).join(1).split('').map((x, i) => i)
trabalha como
> range(4) [0, 1, 2, 3]
fonte
var range = n => Array(n).fill().map((e, i) => i);
x
' quando você realmente usoun
como nome de parâmetroO que se segue é uma adaptação natural da função range () do Python para o 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]
Ele suporta qualquer argumento que pode ser comparado a
0
estop
e pode ser incrementado porstep
. Ele se comporta de forma idêntica à versão Python quando usado com números que não excedemNumber.MAX_SAFE_INTEGER
.Observe os seguintes casos:
[...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
Em contraste com @ Tadeck de , @ Volv do e @ da janka102 resposta que retorno
[]
,undefined
ou entrar num ciclo infinito quandostep
avalia a0
ouNaN
, esta função de gerador gera uma exceção semelhante ao comportamento do Python.fonte
pythonic
imita orange
comportamento do Python da melhor maneira possível usando geradores JS (yield
), suportando os casos de usorange(stop)
erange(start, stop, step)
. Além disso,pythonic
arange
função de retorna umIterator
objeto semelhante ao Python que suportamap
efilter
, portanto, pode-se fazer uma linha sofisticada como:import {range} from 'pythonic'; // ... const results = range(5).map(wouldBeInvokedFiveTimes); // `results` is now an array containing elements from // 5 calls to wouldBeInvokedFiveTimes
Instale usando
npm
:npm install --save pythonic
Divulgação Sou autor e mantenedor do Pythonic
fonte
MDN recomenda esta abordagem: Gerador de sequência (alcance)
// 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"]
fonte
Você pode usar a biblioteca de sublinhados . Ele contém dezenas de funções úteis para trabalhar com matrizes e muito mais.
fonte
Todas as soluções aqui estão se referindo ao intervalo do Python 2 (provavelmente por causa do exemplo de código que você deu). No entanto, no Python 3, o método range () retorna um iterador. JavaScript também tem iteradores e são mais eficientes em termos de espaço do que gerar todo o array e armazená-lo na memória.
Portanto, a representação mais precisa da
range(n)
função do Python 3 éArray(n).keys()
.Por exemplo:
for (let i of Array(n).keys()) { console.log(i) // 0, 1, 2, 3, ..., n }
Mais um exemplo (que já foi abordado nas outras respostas). Convertendo o iterador em uma matriz (ES6):
let ary = [...Array(n).keys()]; // ary = [0, 1, 2, 3, ..., n]
fonte
Ainda sem função embutida equivalente a
range()
, mas com a versão mais recente - ES2015 - você pode construir sua própria implementação. Aqui está uma versão limitada dele. Limitado porque não leva em consideração o parâmetro step. Apenas min, max.const range = (min = null, max = null) => Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
Isso é realizado pelo
Array.from
método capaz de construir um array a partir de qualquer objeto que tenha umalength
propriedade. Portanto, passar um objeto simples com apenas alength
propriedade criará um ArrayIterator que produzirá umlength
número de objetos.fonte
Esta é a minha forma preferida. Ele permite que você especifique uma ou duas entradas como no Python.
function range(start, end) { return Array.from(Array(end||start).keys()).slice(!!end*start) }
fonte
Aqui está outra
es6
implementação do intervalo// 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}`) }
fonte
-20
a-30
?Não, não há nenhum, mas você pode fazer um.
Sou parcial para o comportamento de intervalo do Python3. Você encontrará a seguir a implementação do JavaScript do range () do Python:
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.
fonte
Supondo que você precise de um intervalo simples com uma única etapa:
let range = (start, end)=> { if(start === end) return [start]; return [start, ...range(start + 1, end)]; }
outro
let range = (start, end, step)=> { if(start === end) return [start]; return [start, ...range(start + step, end)]; }
consulte aqui para obter mais informações.
fonte
Como respondi antes: não , não há. Mas você pode fazer o seu próprio. Eu acredito que esta é uma abordagem interessante para ES6. Ele funciona de forma muito semelhante ao Python 2.7
range()
, mas é muito mais dinâmico.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 }
Esta função pode se comportar de três maneiras diferentes (assim como range () do Python):
range(stop)
range(start, stop)
range(start, stop, step)
Estes exemplos:
console.log(range(5)) console.log(range(-2, 2)) console.log(range(2, -2)) console.log(range(10, 20, 2))
Fornecerá a seguinte saída:
[ 0, 1, 2, 3, 4 ] [ -2, -1, 0, 1, 2 ] [ 2, 1, 0, -1, -2 ] [ 10, 12, 14, 16, 18, 20 ]
Observe que, em vez de iterar sobre o array com o
in
operador (como python), você deve usarof
. Portanto, ai
variável assume o valor, e não o índice, do elemento da matriz.for(let i of range(5)) { // do something with i... }
fonte
Uma opção para NodeJs é usar um Buffer:
[...Buffer.alloc(5).keys()] // [ 0, 1, 2, 3, 4 ]
O que é bom é que você pode iterar diretamente no buffer:
Buffer.alloc(5).forEach((_, index) => console.log(index)) // 0 // 1 // 2 // 3 // 4
Você não pode fazer isso com um Array não inicializado:
Array(5).forEach((_, index) => console.log(index)) // undefined
Mas, quem em sã consciência usa um Buffer para uma finalidade como esta;)
fonte
function range(start, stop) { if (typeof stop == 'undefined') { stop = start; start = 0; } result = [...Array(stop).keys()].slice(start, stop); return result; }
fonte
É assim que eu faço
let n = 5 [...Array(n).keys()].map(x=>{console.log(x)})
resultado
fonte