Saya mencari alternatif di bawah ini untuk membuat larik JavaScript yang berisi 1 hingga N di mana N hanya dikenal saat runtime.
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
Bagi saya rasanya harus ada cara untuk melakukan ini tanpa loop.
javascript
arrays
Bapak baptis
sumber
sumber
1 ... N
?Jawaban:
Jika saya mendapatkan apa yang Anda cari, Anda menginginkan array angka
1..n
yang nantinya bisa Anda lewati.Jika ini yang Anda butuhkan, bisakah Anda melakukan ini?
lalu ketika Anda ingin menggunakannya ... (tidak dioptimalkan, misalnya saja)
mis. jika Anda tidak perlu menyimpan apa pun dalam array, Anda hanya perlu satu kontainer dengan panjang yang tepat yang bisa Anda ulangi ... ini mungkin lebih mudah.
Lihat beraksi di sini: http://jsfiddle.net/3kcvm/
sumber
var n = 45;
dan kemudian perulangan dari1..n
akan dilakukan.foo.length = M
--- Info cut off hilang. Lihat dalam aksi ==> jsfiddle.net/ACMXpvar n = 45;
.new Array(45);
tidak "membuat array elemen 45" (dalam arti yang sama seperti[undefined,undefined,..undefined]
halnya). Ini agak "menciptakan array kosong dengan panjang = 45" ([undefined x 45]
), sama denganvar foo = []; foo.length=45;
. Itu sebabnyaforEach
, danmap
tidak akan berlaku dalam kasus ini.Dalam ES6 menggunakan metode Array from () dan keys () .
Versi lebih pendek menggunakan operator spread .
sumber
map
ke array untuk menyesuaikan nilai ([...Array(10).keys()].map(x => x++);
) untuk mulai dari 1map(x => x++)
untukmap(x => ++x)
karena kenaikan didahulukan terjadi setelah nilai kembali :)map
ketika Anda bisa begitu sajaslice
?[...Array(N+1).keys()].slice(1)
keys
dan hanya 1 peta ->Array.from(Array(10)).map((e,i)=>i+1)
from
Array.from(Array(10), (e,i)=>i+1)
Anda dapat melakukannya:
atau dengan nilai acak:
Penjelasan
Pertama, perhatikan yang
Number.call(undefined, N)
setara denganNumber(N)
, yang baru saja kembaliN
. Kami akan menggunakan fakta itu nanti.Array.apply(null, [undefined, undefined, undefined])
setara denganArray(undefined, undefined, undefined)
, yang menghasilkan array tiga elemen dan menetapkanundefined
untuk setiap elemen.Bagaimana Anda bisa menggeneralisasikannya ke elemen N ? Pertimbangkan cara
Array()
kerjanya, yang kira-kira seperti ini:Sejak ECMAScript 5 ,
Function.prototype.apply(thisArg, argsArray)
juga menerima objek seperti array bebek-mengetik sebagai parameter kedua. Jika kita memohonArray.apply(null, { length: N })
, maka itu akan dieksekusiSekarang kita memiliki array N- elemen, dengan setiap elemen diatur ke
undefined
. Ketika kita memanggilnya.map(callback, thisArg)
, setiap elemen akan diatur ke hasilcallback.call(thisArg, element, index, array)
. Oleh karena itu,[undefined, undefined, …, undefined].map(Number.call, Number)
akan memetakan setiap elemen(Number.call).call(Number, undefined, index, array)
, yang sama denganNumber.call(undefined, index, array)
, yang, seperti yang kami amati sebelumnya, dievaluasiindex
. Itu melengkapi array yang elemennya sama dengan indeks mereka.Mengapa harus melalui masalah
Array.apply(null, {length: N})
bukan hanyaArray(N)
? Setelah semua, kedua ekspresi akan menghasilkan array N -elemen elemen yang tidak terdefinisi. Perbedaannya adalah bahwa dalam ekspresi sebelumnya, setiap elemen secara eksplisit diatur ke tidak terdefinisi, sedangkan pada yang terakhir, setiap elemen tidak pernah ditetapkan. Menurut dokumentasi.map()
:Karena itu,
Array(N)
tidak cukup;Array(N).map(Number.call, Number)
akan menghasilkan sebuah array diinisiasi panjang N .Kesesuaian
Karena teknik ini bergantung pada perilaku yang
Function.prototype.apply()
ditentukan dalam ECMAScript 5, itu tidak akan berfungsi di browser pra-ECMAScript 5 seperti Chrome 14 dan Internet Explorer 9.sumber
Function.prototype.call
param pertama adalahthis
objek untuk memetakan secara langsungArray.prototype.map
parameter iterator memiliki kecemerlangan tertentu.map
pada nilai-nilai yang belum ditentukan , menurut pendapat saya. Versi lain (dan mungkin sedikit lebih jelas, meskipun lebih lama) adalah:Array.apply(null, { length: N }).map(function(element, index) { return index; })
Array.apply(null, new Array(N)).map(function(_,i) { return i; })
atau, dalam hal fungsi es6 dan panah, lebih pendek:Array.apply(null, new Array(N)).map((_,i) => i)
Berbagai cara menggunakan ES6
Menggunakan
...
metode spread operator ( ) dan kunciIsi / Peta
Dari Array
Array.dari dan
{ length: N }
retasPerhatikan tentang formulir umum
Semua bentuk di atas array dapat menghasilkan dijalankan dengan nilai-nilai hampir semua yang diinginkan dengan mengubah
i+1
ekspresi diperlukan (misalnyai*2
,-i
,1+i*2
,i%2
dan sebagainya). Jika ekspresi dapat diekspresikan oleh beberapa fungsif
maka bentuk pertama menjadi sederhanaContoh:
Karena array diinisialisasi dengan
undefined
pada setiap posisi, nilaiv
akanundefined
Contoh menampilkan semua formulir
Tampilkan cuplikan kode
Contoh yang lebih generik dengan fungsi initialiser kustom
f
yaituatau bahkan lebih sederhana
Tampilkan cuplikan kode
sumber
k++
, gunakan++k
.Array secara alami mengatur panjangnya. Ketika mereka dilalui, indeks mereka dapat disimpan dalam memori dan direferensikan pada saat itu. Jika indeks acak perlu diketahui,
indexOf
metode ini dapat digunakan.Ini mengatakan, untuk kebutuhan Anda, Anda mungkin hanya ingin mendeklarasikan array dengan ukuran tertentu:
ES6
Sebaran
Memanfaatkan operator spread (
...
) dankeys
metode, memungkinkan Anda untuk membuat array sementara ukuran N untuk menghasilkan indeks, dan kemudian array baru yang dapat ditugaskan ke variabel Anda:Isi / Peta
Pertama-tama Anda dapat membuat ukuran array yang Anda butuhkan, mengisinya dengan undefined dan kemudian membuat array baru menggunakan
map
, yang menetapkan setiap elemen ke indeks.Dari Array
Ini harus dimulai dengan panjang ukuran N dan mengisi array dalam satu lintasan.
Sebagai pengganti komentar dan kebingungan, jika Anda benar-benar ingin menangkap nilai dari 1..N dalam contoh di atas, ada beberapa opsi:
++i
).dalam kasus di mana indeks tidak digunakan - dan mungkin cara yang lebih efisien - adalah membuat array Anda tetapi membuat N mewakili N +1, kemudian bergeser dari depan.
Jadi, jika Anda menginginkan 100 angka:
sumber
Di ES6 Anda dapat melakukan:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Sunting: Diubah
Array(45)
keArray(N)
sejak Anda memperbarui pertanyaan.sumber
.join.split
versi jahat - tapi saya masih berpikir bahwa loop sederhana lebih baik.map
akan segera menjadi standar untuk hal-hal seperti ini.const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
.fill()
itu perlu. Saya melihat bahwa itu adalah ketika saya menguji pada node's repl, tetapi karenaArray(1)[0] === undefined
, apa bedanya panggilan untuk mengisi () padaArray(1).fill(undefined)
make?Gunakan metode _.range Garis Bawah yang sangat populer
sumber
Kemudian dipanggil oleh
Tidak ada cara bawaan untuk melakukan ini dalam Javascript, tetapi ini adalah fungsi utilitas yang benar-benar valid untuk dibuat jika Anda perlu melakukannya lebih dari sekali.
Sunting: Menurut saya, berikut ini adalah fungsi rentang yang lebih baik. Mungkin hanya karena saya bias oleh LINQ, tapi saya pikir ini lebih berguna dalam banyak kasus. Jarak tempuh Anda mungkin beragam.
sumber
Array
alih - alihArray.prototype
karena tidak ada alasan (bahkan mungkin dianggap agak bodoh) untuk memiliki metode ini pada setiap array.Array.range(1, 5)
mungkin akan lebih tepat, tetapi ada sesuatu yang keren tentang penulisan[].range(1, 5)
.foo = [1, 2, 3]; bar = foo.range(0, 10);
. Tapi itu hanya ... membingungkan.bar = Array.range(0, 10)
jauh lebih jelas dan eksplisit. Rentang tidak ada hubungannya dengan instance, jadi tidak ada alasan untuk menjadikannya metode instance.cara tercepat untuk mengisi
Array
v8 adalah:hasilnya adalah:
[0, 1, 2, 3, 4]
sumber
Pertanyaan ini memiliki banyak jawaban yang rumit, tetapi satu kalimat:
Juga, meskipun di atas pendek (dan rapi) untuk menulis, saya pikir yang berikut ini sedikit lebih cepat (untuk panjang maksimal:
127, Int8,
255, Uint8,
32.767, Int16,
65.535, Uint16,
2,147.483.647, Int32,
4.294.967.295, Uint32.
(berdasarkan nilai integer maks ), juga berikut ini di Typed Arays ):
Meskipun solusi ini juga tidak begitu ideal, karena ia menciptakan dua array, dan menggunakan deklarasi variabel tambahan "$" (tidak yakin ada cara untuk menyiasatinya menggunakan metode ini). Saya pikir solusi berikut adalah cara tercepat yang paling mungkin untuk melakukan ini:
Kapan saja setelah pernyataan ini dibuat, Anda dapat menggunakan variabel "arr" sederhana di lingkup saat ini;
Jika Anda ingin membuat fungsi sederhana darinya (dengan beberapa verifikasi dasar):
jadi, dengan fungsi di atas, "satu-liner sederhana" super-lambat di atas menjadi super cepat, bahkan lebih pendek:
sumber
fill
metode baru :Array(255).fill(0,0,255)
Anda bisa menggunakan ini:
sebagai contoh
akan membuat array berikut:
sumber
new Array(10).join().split(',').map(function() {return ++arguments[1]});
?join
, sekali kesplit
, dan sekali untuk hal yang sebenarnya ingin Anda lakukan) tidak baik - Saya tahu mereka tampaknya tidak disukai untuk beberapa alasan, tetapi akan jauh lebih baik menggunakan loop kuno yang bagus !ES6 ini akan melakukan trik:
lihat hasilnya:
sumber
[...Array(N + 1).keys()].slice(1)
akan menghasilkan 1..N[...Array(N + 1).keys()]
kode ini mengembalikan array kosong, tetapi hanya dalam mode produksi, menggunakan mode pengembangan berfungsi..keys()
jawaban sudah diberikan tahun yang lalu dan memiliki 500 + upvotes. Apa yang ditambahkan oleh jawaban Anda?Jika Anda menggunakan d3.js di aplikasi Anda seperti saya, D3 menyediakan fungsi pembantu yang melakukan ini untuk Anda.
Jadi untuk mendapatkan array dari 0 hingga 4, semudah:
dan untuk mendapatkan array dari 1 hingga 5, saat Anda meminta:
Lihatlah tutorial ini untuk informasi lebih lanjut.
sumber
Menggunakan operator penyebaran ES2015 / ES6
sumber
i + 1
akan lebih masuk akal daripada++i
.Ini mungkin cara tercepat untuk menghasilkan array angka
Terpendek
Di barisan
Jika Anda ingin memulai dari 1
Ingin fungsi?
MENGAPA?
while
adalah loop tercepatPengaturan langsung lebih cepat daripada
push
[]
lebih cepat darinew Array(10)
ini singkat ... lihat kode pertama. kemudian lihat semua fungsi lain di sini.
Jika Anda suka tidak bisa hidup tanpa untuk
atau
sumber
console.time()
untuk mendapatkan intuisi, tetapi sebagai buktinya, Anda memerlukan jsperf.com DAN itu menunjukkan kepada Anda hasil cross-browser dari orang lain (perangkat keras yang berbeda, dll)var a=[],b=N;while(b--){a[b]=a+1};
Jika Anda menggunakan lodash, Anda dapat menggunakan _.range :
Contoh:
sumber
cara baru untuk mengisi
Array
adalah:hasilnya adalah:
[0, 1, 2, 3, 4]
sumber
dengan ES6 yang dapat Anda lakukan:
sumber
map
danforEach
akan berfungsi.Laporan Ringkasan Akhir .. Drrruummm Rolll -
Ini adalah kode terpendek untuk menghasilkan Array ukuran N (di sini 10) tanpa menggunakan ES6 . Versi Cocco di atas sudah dekat tapi bukan yang terpendek.
Tetapi pemenang yang tidak perlu dari golf Kode ini (persaingan untuk memecahkan masalah tertentu dalam byte kode sumber paling sedikit) adalah Niko Ruotsalainen . Menggunakan Array Constructor dan operator penyebaran ES6 . (Sebagian besar sintaks ES6 adalah jenis huruf yang valid, tetapi mengikuti tidak. Jadi berhati-hatilah saat menggunakannya)
sumber
a
. Lingkaran harusfor(var a=[];n--;a[n]=n+1)
Ada cara lain dalam ES6, menggunakan Array.from yang mengambil 2 argumen, yang pertama adalah arrayLike (dalam hal ini objek dengan
length
properti), dan yang kedua adalah fungsi pemetaan (dalam hal ini kami memetakan item ke indeksnya)ini lebih pendek dan dapat digunakan untuk urutan lain seperti menghasilkan bilangan genap
Juga ini memiliki kinerja yang lebih baik daripada kebanyakan cara lain karena hanya loop sekali melalui array. Periksa snippit untuk beberapa perbandingan
sumber
Array.from({length:N}, (v,i) => i+1)
Menggunakan metode Array baru dan
=>
sintaks fungsi dari standar ES6 (hanya Firefox pada saat penulisan).Dengan mengisi lubang dengan
undefined
:Array.from
mengubah "lubang" menjadiundefined
begituArray.map
berfungsi seperti yang diharapkan:sumber
Array.from({length: N}, (v, k) => k)
.Array.prototype.map.call
, misalnya untuk NodeLists kembali daridocument.querySelectorAll
. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…Array.from
yang mengubah nilai jarang menjadi tidak terdefinisi. MelainkanArray(5)
disebut sebagai objek argumen yang pada gilirannya menginterpretasikan nilai jarang sebagai nilai yang tidak ditentukan :)sumber
[...Array(9)].map((_, i) => i)
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sumber
Dalam ES6:
ES5:
sumber
Hanya versi ES6 lainnya .
Dengan memanfaatkan
Array.from
argumen opsional kedua:Kita dapat membangun array bernomor dari
Array(10)
posisi kosong :sumber
[...Array(11).keys()].slice(1)
.Tampaknya satu-satunya rasa yang saat ini tidak ada dalam daftar jawaban yang agak lengkap ini adalah yang menampilkan generator; jadi untuk memperbaiki itu:
yang dapat digunakan demikian:
Hal yang menyenangkan tentang ini adalah Anda tidak hanya perlu menambah ... Untuk mengambil inspirasi dari jawaban yang diberikan @ igor-shubin, Anda dapat membuat susunan tebusan dengan sangat mudah:
Dan bukan sesuatu
yang panjangoperasional mahal seperti:Anda bisa melakukannya:
sumber
Anda dapat menggunakan isi Array dan memetakan dari Es6; seperti beberapa orang yang menyarankan jawaban yang mereka berikan untuk pertanyaan ini. Berikut adalah beberapa contoh:
Saya lebih suka ini karena saya merasa lurus dan mudah.
sumber
Sumber: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
sumber
Menggunakan ES6
sumber
Array.from(Array(n))
jika operator spread tidak didukung.map
MDN berikut : "Tidak dipanggil untuk elemen array yang hilang (yaitu, indeks yang belum pernah ditetapkan, yang memiliki telah dihapus atau yang belum pernah diberi nilai). "Object.keys(Array.apply(0, Array(3))).map(Number)
Pengembalian
[0, 1, 2]
. Sangat mirip dengan jawaban sempurna Igor Shubin , tetapi dengan sedikit tipu daya (dan satu karakter lebih lama).Penjelasan:
Array(3) // [undefined × 3]
Hasilkan array dengan panjang n = 3. Sayangnya array ini hampir tidak berguna bagi kita, jadi kita harus ...Array.apply(0,Array(3)) // [undefined, undefined, undefined]
membuat array iterable. Catatan: null lebih umum sebagai arg pertama yang berlaku tetapi 0 lebih pendek.Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']
kemudian dapatkan kunci-kunci array (berfungsi karena Array adalah tipe array adalah objek dengan indeks untuk kunci.Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]
dan memetakan di atas tombol, mengubah string menjadi angka.sumber