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;
}
javascript
python
Clwen
sumber
sumber
range()
kerja Python, sehingga Anda dapat menggunakannya. Tidak ada fungsi seperti itu di JavaScript, tetapi ada beberapa plugin untuk kerangka kerja yang berbeda, sepertiRange
kelas untuk MooTools .Jawaban:
Tidak , tidak ada, tapi Anda bisa membuatnya .
Implementasi JavaScript dari Python
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.
Perbandingan antara
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.sumber
stop
lebih besar daristart
(dan tukar jika tidak).start >= stop
mengarahkan ke array kosong diperlukan jika tujuannya benar-benar meniru jangkauan Python. Dan menurut saya itu lebih intuitif.start >= stop
tidak cukup sederhana agar fungsi ini berperilaku sepertirange()
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()]
sumber
let range = n => [...Array(n).keys()]
const
sebanyak mungkin, tetapi di sini hanya akan menjadi referensi ke array, jadi array akan tetap dapat diedit: 'Dconst
akan 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
yield
kata kunci standar ES6 , dan mereka didukung secara universal di seluruh platform. Sebuah contoh dari malasrange()
menggunakanyield
dapat 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 toxrange
di 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
sumber
step
argumen 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 ).range
memiliki 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
sumber
step
parameter, tetapi ketikastop
tidak diteruskan, keduanyastart
danstop
perlu diubah. Saya akan memperbaruinyaPort
range
fungsi 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); => []
sumber
Dapat dicapai dengan memasang iterator ke
Number
prototipeNumber.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
sumber
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);
sumber
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]
sumber
Untuk mendapatkan berbagai ukuran
x
, berikut adalah satu baris tanpa menggunakan pustaka apa punvar range = n => Array(n + 1).join(1).split('').map((x, i) => i)
bekerja sebagai
> range(4) [0, 1, 2, 3]
sumber
var range = n => Array(n).fill().map((e, i) => i);
x
' ketika Anda benar-benar menggunakann
nama parameterBerikut 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
0
danstop
dan dapat ditambah denganstep
. Ini berperilaku identik dengan versi Python saat digunakan dengan angka yang tidak melebihiNumber.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
[]
,undefined
atau memasuki loop tak terbatas saatstep
mengevaluasi ke0
atauNaN
, fungsi generator ini menampilkan pengecualian yang mirip dengan perilaku Python.sumber
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 }
sumber
pythonic
menirurange
perilaku Python sebaik mungkin dengan menggunakan generator JS (yield
), mendukung baik kasus penggunaanrange(stop)
maupunrange(start, stop, step)
kasus. Selain itu,pythonic
'srange
fungsi mengembalikan sebuahIterator
objek yang sama untuk Python yang mendukungmap
danfilter
, 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
sumber
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"]
sumber
Anda dapat menggunakan perpustakaan garis bawah . Ini berisi lusinan fungsi yang berguna untuk bekerja dengan array dan banyak lagi.
sumber
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 adalahArray(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]
sumber
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.from
metode yang mampu membangun larik dari objek apa pun yang memilikilength
properti. Jadi meneruskan objek sederhana hanya denganlength
properti akan membuat ArrayIterator yang akan menghasilkanlength
sejumlah objek.sumber
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) }
sumber
Berikut adalah
es6
implementasi 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}`) }
sumber
-20
to-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.
sumber
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.
sumber
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
in
operator (seperti python), Anda harus menggunakanof
. Jadii
variabel mengasumsikan nilai, dan bukan indeks, dari elemen array.for(let i of range(5)) { // do something with i... }
sumber
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;)
sumber
Begini cara saya melakukannya
let n = 5 [...Array(n).keys()].map(x=>{console.log(x)})
keluaran
0 1 2 3 4
sumber