Apakah ada fungsi dalam JavaScript yang mirip dengan Python range()?
Saya pikir harus ada cara yang lebih baik daripada menulis baris berikut setiap saat:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
Jawaban:
Tidak , tidak ada, tapi Anda bisa membuatnya .
range()Mencoba meniru cara kerjanya dengan Python , saya akan membuat fungsi yang mirip dengan ini:
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;
};
Lihat jsfiddle ini untuk bukti.
range()di JavaScript dan PythonIni bekerja dengan cara berikut:
range(4)kembali [0, 1, 2, 3],range(3,6)kembali [3, 4, 5],range(0,10,2)kembali [0, 2, 4, 6, 8],range(10,0,-1)kembali [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],range(8,2,-2)kembali [8, 6, 4],range(8,2)kembali [],range(8,2,2)kembali [],range(1,5,-1)kembali [],range(1,5,-2)kembali [],dan mitra Python-nya bekerja dengan cara yang persis sama (setidaknya dalam kasus yang disebutkan):
>>> 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)
[]
Jadi jika Anda memerlukan fungsi untuk bekerja mirip dengan Python range(), Anda dapat menggunakan solusi yang disebutkan di atas.
stoplebih besar dari start(dan tukar jika tidak).
start >= stopmengarahkan ke array kosong diperlukan jika tujuannya benar-benar meniru jangkauan Python. Dan menurut saya itu lebih intuitif.
start >= stoptidak cukup sederhana agar fungsi ini berperilaku seperti range()di Python. Saya telah memperbarui jawaban saya.
Untuk rentang yang sangat sederhana di ES6:
let range = n => Array.from(Array(n).keys())
Dari komentar bigOmega , ini dapat dipersingkat menggunakan sintaks Spread :
let range = n => [...Array(n).keys()]
let range = n => [...Array(n).keys()]
constsebanyak mungkin, tetapi di sini hanya akan menjadi referensi ke array, jadi array akan tetap dapat diedit: 'D
constakan berlaku untuk fungsi itu sendiri, bukan nilai kembaliannya. Anda mungkin tidak ingin mengubah fungsi dengan cara apa pun.
2018: jawaban ini terus mendapatkan suara positif, jadi inilah pembaruannya. Kode di bawah ini sudah usang, tetapi untungnya generator dan yieldkata kunci standar ES6 , dan mereka didukung secara universal di seluruh platform. Sebuah contoh dari malas range()menggunakan yielddapat ditemukan di sini .
Selain apa yang telah disebutkan, Javascript 1.7+ menyediakan dukungan untuk iterator dan generator yang dapat digunakan untuk membuat versi malas, hemat memori range, simlar to xrangedi 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
stepargumen dan mengujinya pada nilai-nilai dari jawaban saya ? Jawaban Anda bagus untuk aplikasi yang memiliki browser yang sangat spesifik (tidak akan berfungsi di Google Chrome, Safari, dan versi IE sebelum 9: stackoverflow.com/a/2209743/548696 ).
rangememiliki nilai "terakhir" yang dikecualikan (jadi harus digunakan >=sebagai pengganti >kode di atas)
Menggabungkan kedua jawaban dari @Tadeck dan @georg , saya menemukan ini:
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;
}
}
Untuk menggunakannya dalam loop for Anda memerlukan 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
stepparameter, tetapi ketika stoptidak diteruskan, keduanya startdan stopperlu diubah. Saya akan memperbaruinya
Port rangefungsi dari Python 2 disediakan oleh pustaka utilitas underscore.js dan lodash (bersama dengan banyak alat berguna lainnya). Contoh disalin dari dokumen garis bawah:
_.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);
=> []
Dapat dicapai dengan memasang iterator ke Numberprototipe
Number.prototype[Symbol.iterator] = function* () {
for (var i = 0; i <= this; i++) {
yield i
}
}
[...5] // will result in [0,1,2,3,4,5]
Diambil dari kursus Kyle Simpson Rethinking Asynchronous JavaScript
Berikut adalah ekstensi kecil untuk salah satu jawaban jika Anda perlu menentukan posisi awal dan akhir rentang:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
Ini dia.
Ini akan menulis (atau menimpa) nilai setiap indeks dengan nomor indeks.
Array.prototype.writeIndices = function( n ) {
for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
return this;
};
Jika Anda tidak memberikan nomor, itu akan menggunakan panjang Array saat ini.
Gunakan seperti ini:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Untuk mendapatkan berbagai ukuran x, berikut adalah satu baris tanpa menggunakan pustaka apa pun
var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
bekerja sebagai
> range(4)
[0, 1, 2, 3]
var range = n => Array(n).fill().map((e, i) => i);
x' ketika Anda benar-benar menggunakan nnama parameter
Berikut ini adalah adaptasi alami dari fungsi range () Python ke 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]
Ini mendukung argumen apa pun yang dapat dibandingkan dengan 0dan stopdan dapat ditambah dengan step. Ini berperilaku identik dengan versi Python saat digunakan dengan angka yang tidak melebihi Number.MAX_SAFE_INTEGER.
Harap perhatikan kasus sudut berikut:
[...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
Berbeda dengan jawaban @ Tadeck , @ Volv dan @ janka102 yang mengembalikan [], undefinedatau memasuki loop tak terbatas saat stepmengevaluasi ke 0atau NaN, fungsi generator ini menampilkan pengecualian yang mirip dengan perilaku Python.
Lebih disempurnakan dengan parameter default 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
}
pythonicmeniru rangeperilaku Python sebaik mungkin dengan menggunakan generator JS ( yield), mendukung baik kasus penggunaan range(stop)maupun range(start, stop, step)kasus. Selain itu, pythonic's rangefungsi mengembalikan sebuah Iteratorobjek yang sama untuk Python yang mendukung mapdan filter, sehingga orang bisa melakukan mewah satu kalimat seperti:
import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes
Instal menggunakan npm:
npm install --save pythonic
Pengungkapan Saya penulis dan pengelola Pythonic
MDN merekomendasikan pendekatan ini: Generator urutan (kisaran)
// 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"]
Anda dapat menggunakan perpustakaan garis bawah . Ini berisi lusinan fungsi yang berguna untuk bekerja dengan array dan banyak lagi.
Apakah ada fungsi dalam JavaScript yang mirip dengan range () Python?
Semua solusi di sini mengacu pada kisaran Python 2 (mungkin karena contoh kode yang Anda berikan). Namun dalam Python 3, metode range () mengembalikan sebuah iterator. JavaScript juga memiliki iterator dan mereka lebih hemat ruang daripada menghasilkan seluruh larik dan menyimpannya dalam memori.
Jadi representasi range(n)fungsi Python 3 yang lebih akurat adalah Array(n).keys().
Sebagai contoh:
for (let i of Array(n).keys()) {
console.log(i) // 0, 1, 2, 3, ..., n
}
Satu contoh lagi (yang telah tercakup dalam jawaban lain). Mengonversi iterator menjadi array (ES6):
let ary = [...Array(n).keys()];
// ary = [0, 1, 2, 3, ..., n]
Masih belum ada fungsi range()bawaan yang setara , tetapi dengan versi terbaru - ES2015 - Anda dapat membuat implementasi Anda sendiri. Ini versi terbatasnya. Terbatas karena tidak memperhitungkan parameter langkah. Hanya min, maks.
const range = (min = null, max = null) =>
Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
Ini dilakukan dengan Array.frommetode yang mampu membangun larik dari objek apa pun yang memiliki lengthproperti. Jadi meneruskan objek sederhana hanya dengan lengthproperti akan membuat ArrayIterator yang akan menghasilkan lengthsejumlah objek.
Ini cara yang saya pilih. Ini memungkinkan Anda untuk menentukan satu atau dua input seperti di Python.
function range(start, end) {
return Array.from(Array(end||start).keys()).slice(!!end*start)
}
Berikut adalah es6implementasi lain dari rentang tersebut
// 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}`)
}
-20to -30?
Tidak, tidak ada, tapi Anda bisa membuatnya.
Saya parsial terhadap perilaku jangkauan Python3. Di bawah ini Anda akan menemukan implementasi JavaScript dari range 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.
Dengan asumsi Anda membutuhkan rentang sederhana dengan satu langkah:
let range = (start, end)=> {
if(start === end) return [start];
return [start, ...range(start + 1, end)];
}
lain
let range = (start, end, step)=> {
if(start === end) return [start];
return [start, ...range(start + step, end)];
}
lihat di sini untuk lebih lanjut.
Apakah ada fungsi dalam JavaScript yang mirip dengan range () Python?
Seperti yang telah dijawab sebelumnya: tidak , tidak ada. Tapi Anda bisa membuatnya sendiri. Saya yakin ini adalah pendekatan yang menarik untuk ES6. Cara kerjanya sangat mirip dengan Python 2.7 range(), tetapi jauh lebih dinamis.
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
}
Fungsi ini dapat berperilaku dalam tiga cara berbeda (seperti range ()) Python:
range(stop)range(start, stop)range(start, stop, step)Contoh berikut:
console.log(range(5))
console.log(range(-2, 2))
console.log(range(2, -2))
console.log(range(10, 20, 2))
Akan memberi Anda output berikut:
[ 0, 1, 2, 3, 4 ]
[ -2, -1, 0, 1, 2 ]
[ 2, 1, 0, -1, -2 ]
[ 10, 12, 14, 16, 18, 20 ]
Perhatikan bahwa alih-alih mengulang array dengan inoperator (seperti python), Anda harus menggunakan of. Jadi ivariabel mengasumsikan nilai, dan bukan indeks, dari elemen array.
for(let i of range(5))
{
// do something with i...
}
Opsi untuk NodeJs adalah menggunakan Buffer:
[...Buffer.alloc(5).keys()]
// [ 0, 1, 2, 3, 4 ]
Yang menyenangkan adalah Anda dapat melakukan iterasi langsung di buffer:
Buffer.alloc(5).forEach((_, index) => console.log(index))
// 0
// 1
// 2
// 3
// 4
Anda tidak dapat melakukannya dengan Array yang tidak diinisialisasi:
Array(5).forEach((_, index) => console.log(index))
// undefined
Tapi, siapa yang waras menggunakan Buffer untuk tujuan seperti ini;)
Begini cara saya melakukannya
let n = 5
[...Array(n).keys()].map(x=>{console.log(x)})
keluaran
0
1
2
3
4
range()kerja Python, sehingga Anda dapat menggunakannya. Tidak ada fungsi seperti itu di JavaScript, tetapi ada beberapa plugin untuk kerangka kerja yang berbeda, sepertiRangekelas untuk MooTools .