Katakanlah saya memiliki array Javascript yang terlihat sebagai berikut:
["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.
Pendekatan apa yang cocok untuk memotong (memecah) array menjadi banyak array yang lebih kecil dengan, katakanlah, 10 elemen paling banyak?
javascript
arrays
split
Industri
sumber
sumber
const chunk = (arr, n) => arr.length ? [arr.slice(0, n), ...chunk(arr.slice(n), n)] : []
yang bagus dan pendek tetapi tampaknya memakan waktu sekitar 256 × selama jawaban @ AymKdn untuk 1.000 elemen, dan 1.058 × selama 10.000 elemen!Jawaban:
The array.slice Metode dapat mengekstrak sepotong dari awal, tengah, atau akhir array untuk tujuan apa pun yang Anda butuhkan, tanpa mengubah array asli.
sumber
chunk
keberadaan0
. (infinite loop)const array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)).fill().map((_, index) => index * chunk_size).map(begin => array.slice(begin, begin + chunk_size));
.Dimodifikasi dari jawaban oleh dbaseman: https://stackoverflow.com/a/10456344/711085
tambahan kecil :
Saya harus menunjukkan bahwa solusi di atas adalah tidak-elegan (dalam pikiran saya) untuk digunakan
Array.map
. Ini pada dasarnya melakukan hal berikut, di mana ~ adalah gabungan:Ini memiliki waktu berjalan asimptotik yang sama dengan metode di bawah ini, tetapi mungkin faktor konstan yang lebih buruk karena membangun daftar kosong. Orang dapat menulis ulang ini sebagai berikut (kebanyakan sama dengan metode Blazemonger, itulah sebabnya saya awalnya tidak mengirimkan jawaban ini):
Metode yang lebih efisien:
Cara yang saya sukai saat ini adalah di atas, atau salah satu dari yang berikut:
Demo:
Atau jika Anda tidak ingin fungsi Array.range, sebenarnya hanya satu-liner (tidak termasuk fluff):
atau
sumber
chunk
fungsi pada array tidak benar-benar melebihi kompleksitas tambahan yang Anda tambahkan dan bug halus yang dapat menyebabkan prototipe built-in dapat menyebabkan.array.map(function(i)
tidakarray.map(function(elem,i)
meskipunBerikut ini adalah versi ES6 menggunakan pengurangan
Dan Anda siap untuk membuat rantai lebih lanjut peta / mengurangi transformasi. Array input Anda dibiarkan utuh
Jika Anda lebih suka versi yang lebih pendek tetapi kurang mudah dibaca, Anda dapat memercikkannya
concat
ke dalam campuran untuk hasil akhir yang sama:sumber
5/2 = 2.5
danMath.floor(2.5) = 2
item dengan indeks 5 akan ditempatkan di bucket 2Cobalah untuk menghindari mucking dengan prototipe asli, termasuk Array.prototype, jika Anda tidak tahu siapa yang akan mengkonsumsi kode Anda (pihak ke-3, rekan kerja, diri Anda di kemudian hari, dll.).
Ada beberapa cara untuk memperluas prototipe dengan aman (tetapi tidak di semua browser) dan ada cara-cara untuk menggunakan objek yang dibuat dari prototipe yang diperluas dengan aman, tetapi aturan praktis yang lebih baik adalah mengikuti Prinsip Terkejut dan menghindari praktik-praktik ini sama sekali.
Jika Anda punya waktu, lihat pembicaraan Andrew Dupont JSConf 2011, "Semuanya Diizinkan: Memperluas Built-in" , untuk diskusi yang baik tentang topik ini.
Tetapi kembali ke pertanyaan, sementara solusi di atas akan bekerja, mereka terlalu rumit dan membutuhkan overhead komputasi yang tidak perlu. Inilah solusi saya:
sumber
Saya menguji jawaban yang berbeda ke jsperf.com. Hasilnya tersedia di sana: https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds
Dan fungsi tercepat (dan yang berfungsi dari IE8) adalah yang ini:
sumber
Saya lebih suka menggunakan metode sambatan :
sumber
var clone = [...array]
kemudian lakukan pemeriksaan panjang dan splicing pada array yang dikloning itu.array = array.slice()
yang juga membuat salinan dangkal.One-liner dalam ECMA 6
sumber
list
array asli.map((_,i) => list.slice(i*chuckSize,i*chuckSize+chuckSize))
Pertanyaan lama: Jawaban baru! Saya sebenarnya bekerja dengan jawaban dari pertanyaan ini dan meminta seorang teman untuk memperbaikinya! Jadi begini:
sumber
.length
jauh lebih besar daripada ukuran chunkn
). Jika ini adalah bahasa yang malas (tidak seperti javascript), algoritma ini tidak akan menderita waktu O (N ^ 2). Yang mengatakan, implementasi rekursif elegan. Anda mungkin dapat memodifikasinya untuk meningkatkan kinerja dengan terlebih dahulu mendefinisikan fungsi pembantu yang berulangarray,position
, kemudian mengirim:Array.prototype.chunk
mengembalikan [fungsi pembantu Anda] (...)var chunk = (arr, n) => { if ( !arr.length ) return []; return [ arr.slice( 0, n ) ].concat( chunk(arr.slice(n), n) ) }
Saat ini Anda dapat menggunakan fungsi chunk lodash untuk memecah array menjadi array yang lebih kecil https://lodash.com/docs#chunk Tidak perlu bermain-main lagi dengan loop!
sumber
Ada banyak jawaban tetapi inilah yang saya gunakan:
Pertama, periksa sisa ketika membagi indeks dengan ukuran chunk.
Jika ada sisa maka kembalikan saja array akumulator.
Jika tidak ada sisa maka indeks dapat dibagi dengan ukuran chunk, jadi ambil irisan dari array asli (mulai dari indeks saat ini) dan tambahkan ke array akumulator.
Jadi, array akumulator yang dikembalikan untuk setiap iterasi dari pengurangan terlihat seperti ini:
sumber
Menggunakan generator
sumber
Ok, mari kita mulai dengan yang cukup ketat:
Yang digunakan seperti ini:
Maka kita memiliki fungsi peredam ketat ini:
Yang digunakan seperti ini:
Karena anak kucing mati ketika kita mengikat
this
nomor, kita dapat melakukan kari manual seperti ini sebagai gantinya:Yang digunakan seperti ini:
Kemudian fungsi yang masih cukup ketat yang melakukan semuanya sekaligus:
sumber
(p[i/n|0] || (p[i/n|0] = []))
, jadi Anda tidak menetapkan nilai, jika tidak perlu ...Saya bertujuan menciptakan solusi non-mutasi sederhana di ES6 murni. Keanehan dalam javascript membuatnya perlu mengisi array kosong sebelum memetakan :-(
Versi ini dengan rekursi tampak lebih sederhana dan lebih menarik:
Fungsi array ES6 yang sangat lemah menghasilkan puzzle yang bagus :-)
sumber
0
darifill
, yang membuatfill
tampilan sedikit lebih masuk akal, imho.Saya pikir ini solusi rekursif yang bagus dengan sintaks ES6:
sumber
Membuat paket npm untuk https://www.npmjs.com/package/array.chunk ini
Saat menggunakan TypedArray
sumber
slice
metode untukTypedArray
, kita dapat menggunakansubarray
sebagai gantinya developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Jika Anda menggunakan versi EcmaScript> = 5.1, Anda dapat mengimplementasikan versi fungsional
chunk()
menggunakan array.reduce () yang memiliki kompleksitas O (N):Penjelasan masing
// nbr
- masing di atas:chunkSize
itemKari berdasarkan pada
chunkSize
:Anda dapat menambahkan
chunk()
fungsi keArray
objek global :sumber
sumber
sumber
Pendekatan ES2015 berikut berfungsi tanpa harus mendefinisikan fungsi dan langsung pada array anonim (contoh dengan ukuran chunk 2):
Jika Anda ingin mendefinisikan fungsi untuk ini, Anda bisa melakukannya sebagai berikut (meningkatkan komentar K ._ pada jawaban Blazemonger ):
sumber
Dan ini akan menjadi kontribusi saya untuk topik ini. Saya kira
.reduce()
itu cara terbaik.Tetapi implementasi di atas tidak terlalu efisien karena
.reduce()
dijalankan melalui semuaarr
fungsi. Pendekatan yang lebih efisien (sangat dekat dengan solusi imperatif tercepat) adalah, mengulangi pengurangan array (yang akan dipotong) karena kita dapat menghitung ukurannya terlebih dahuluMath.ceil(arr/n);
. Setelah kita memiliki array hasil kosong sepertiArray(Math.ceil(arr.length/n)).fill();
yang lain adalah memetakan irisanarr
array ke dalamnya.sumber
Gunakan potongan dari lodash
sumber
Satu lagi solusi menggunakan
arr.reduce()
:Solusi ini sangat mirip dengan solusi oleh Steve Holgado . Namun, karena solusi ini tidak menggunakan penyebaran array dan tidak membuat array baru dalam fungsi peredam, itu lebih cepat (lihat uji jsPerf ) dan lebih mudah dibaca (sintaksis sederhana) daripada solusi lain.
Pada setiap iterasi ke - n (di mana n =
size
; mulai dari iterasi pertama), array akumulator (acc
) ditambahkan dengan potongan array ()arr.slice(i, i + size)
) dan kemudian dikembalikan. Di iterasi lain, array akumulator dikembalikan apa adanya.Jika
size
nol, metode mengembalikan array kosong. Jikasize
negatif, metode mengembalikan hasil yang rusak. Jadi, jika diperlukan dalam kasus Anda, Anda mungkin ingin melakukan sesuatu tentangsize
nilai - nilai negatif atau non-positif .Jika kecepatan penting dalam kasus Anda,
for
loop sederhana akan lebih cepat daripada menggunakanarr.reduce()
(lihat tes jsPerf ), dan beberapa mungkin menemukan gaya ini lebih mudah dibaca:sumber
Untuk solusi fungsional, gunakan Ramda :
Di mana
popularProducts
array input Anda,5
adalah ukuran chunksumber
Pendekatan satu garis ES6 berdasarkan
Array.prototype
reduce
danpush
metode:sumber
Versi ES6 Generator
sumber
const
sebagai gantinya.Ini adalah solusi paling efisien dan mudah yang dapat saya pikirkan:
sumber
ES6 menyebar fungsional #ohmy #ftw
sumber
Berikut adalah solusi rekursif yang mengoptimalkan panggilan ekor.
sumber
EDIT: @ mblase75 menambahkan kode yang lebih ringkas ke jawaban sebelumnya ketika saya menulis milik saya, jadi saya sarankan pergi dengan solusinya.
Anda dapat menggunakan kode seperti ini:
Ubah nilai
arraySize
untuk mengubah panjang maksimum array yang lebih kecil.sumber
Berikut ini adalah solusi non-mutasi yang hanya menggunakan rekursi dan slice ().
Maka cukup gunakan saja
splitToChunks([1, 2, 3, 4, 5], 3)
untuk mendapatkannya[[1, 2, 3], [4, 5]]
.Berikut ini biola untuk Anda coba: https://jsfiddle.net/6wtrbx6k/2/
sumber