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;
}
Respostas:
Não , não há nenhum, mas você pode fazer um .
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.
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.
stopseja maior que start(e troque-os se não).
start >= stopconduzir 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 >= stopnão é suficiente para esta função se comportar como range()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()]
let range = n => [...Array(n).keys()]
consto máximo possível, mas aqui será apenas uma referência ao array, então o array ainda seria editável: 'D
constse 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 yieldpalavra - chave, e eles são universalmente suportados em todas as plataformas. Um exemplo de range()uso preguiçoso yieldpode 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 ao xrangedo 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
stepargumento 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 ).
rangetem 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
stepparâmetro, mas quando stopnão é passado, ambos starte stopprecisam ser alterados. Vou atualizá-lo
Uma porta da rangefunçã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);
=> []
Pode ser alcançado anexando um iterador ao Numberprotótipo
Number.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
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);
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]
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
}
Para obter um array de tamanho x, aqui está um one-liner sem usar qualquer biblioteca
var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
trabalha como
> range(4)
[0, 1, 2, 3]
var range = n => Array(n).fill().map((e, i) => i);
x' quando você realmente usou ncomo nome de parâmetro
O 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 0e stope pode ser incrementado por step. Ele se comporta de forma idêntica à versão Python quando usado com números que não excedem Number.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 [], undefinedou entrar num ciclo infinito quando stepavalia a 0ou NaN, esta função de gerador gera uma exceção semelhante ao comportamento do Python.
pythonicimita o rangecomportamento do Python da melhor maneira possível usando geradores JS ( yield), suportando os casos de uso range(stop)e range(start, stop, step). Além disso, pythonica rangefunção de retorna um Iteratorobjeto semelhante ao Python que suporta mape filter, 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
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"]
Você pode usar a biblioteca de sublinhados . Ele contém dezenas de funções úteis para trabalhar com matrizes e muito mais.
Existe uma função em JavaScript semelhante a range () do Python?
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]
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.frommétodo capaz de construir um array a partir de qualquer objeto que tenha uma lengthpropriedade. Portanto, passar um objeto simples com apenas a lengthpropriedade criará um ArrayIterator que produzirá um lengthnúmero de objetos.
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)
}
Aqui está outra es6implementaçã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}`)
}
-20a -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.
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.
Existe uma função em JavaScript semelhante a range () do Python?
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 inoperador (como python), você deve usar of. Portanto, a ivariável assume o valor, e não o índice, do elemento da matriz.
for(let i of range(5))
{
// do something with i...
}
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;)
É assim que eu faço
let n = 5
[...Array(n).keys()].map(x=>{console.log(x)})
resultado
0
1
2
3
4
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, comoRangeclasse para MooTools .