Adakah cara yang bagus untuk membagi koleksi n
beberapa bagian dengan LINQ? Belum tentu merata tentunya.
Yaitu, saya ingin membagi koleksi menjadi sub-koleksi, yang masing-masing berisi subset elemen, di mana koleksi terakhir bisa compang-camping.
c#
.net
linq
data-structures
Simon_Weaver
sumber
sumber
Jawaban:
Linq murni dan solusi paling sederhana adalah seperti yang ditunjukkan di bawah ini.
sumber
.AsEnumerable()
tidak diperlukan, IGrouping <T> sudah menjadi IEnumerable <T>.EDIT: Oke, sepertinya saya salah membaca pertanyaan. Saya membacanya sebagai "potongan dengan panjang n" daripada "potongan n". Doh! Mempertimbangkan untuk menghapus jawaban ...
(Jawaban asli)
Saya tidak percaya ada cara untuk mempartisi, meskipun saya bermaksud untuk menulis satu cara untuk menambahkan LINQ ke Objek. Marc Gravell memiliki implementasi di sini meskipun saya mungkin akan memodifikasinya untuk mengembalikan tampilan hanya-baca:
sumber
yield return
. Ini membutuhkan satu batch untuk berada di memori pada satu waktu, tapi itu saja.sumber
var dept = {1,2,3,4,5}
. Setelah dipecah hasilnya sepertidept1 = {1,3,5}
dandept2 = { 2,4 }
dimanaparts = 2
. Tetapi hasil yang saya butuhkan adalahdept1 = {1,2,3}
dandept2 = {4,5}
int columnLength = (int)Math.Ceiling((decimal)(list.Count()) / parts);
kemudian melakukan pembagian.GroupBy(x => x.index / columnLength)
. Satu downside adalah Count () menyebutkan daftar.Oke, saya akan melempar topi saya ke atas ring. Keuntungan dari algoritme saya:
Kode:
Seperti yang ditunjukkan pada komentar di bawah, pendekatan ini tidak benar-benar menjawab pertanyaan awal yang meminta sejumlah bagian tetap dengan panjang yang kira-kira sama. Meskipun demikian, Anda masih dapat menggunakan pendekatan saya untuk menyelesaikan pertanyaan asli dengan menyebutnya seperti ini:
Jika digunakan dengan cara ini, pendekatannya bukan lagi O (1) karena operasi Count () adalah O (N).
sumber
Ini sama dengan jawaban yang diterima, tetapi representasi yang jauh lebih sederhana:
Metode di atas membagi
IEnumerable<T>
menjadi sejumlah N potongan dengan ukuran yang sama atau mendekati ukuran yang sama.Metode di atas membagi
IEnumerable<T>
menjadi potongan-potongan dengan ukuran tetap yang diinginkan dengan jumlah total potongan menjadi tidak penting - yang bukan pertanyaannya.Masalah dengan
Split
metode ini, selain lebih lambat, adalah ia mengacak keluaran dalam arti bahwa pengelompokan akan dilakukan berdasarkan kelipatan ke-i dari N untuk setiap posisi, atau dengan kata lain Anda tidak mendapatkan potongannya. dalam urutan aslinya.Hampir setiap jawaban di sini tidak menjaga ketertiban, atau tentang mempartisi dan tidak memisahkan, atau jelas salah. Coba ini yang lebih cepat, menjaga ketertiban tetapi sedikit lebih bertele-tele:
Metode yang setara untuk
Partition
operasi di sinisumber
Saya telah menggunakan fungsi Partisi yang saya posting sebelumnya cukup sering. Satu-satunya hal buruk tentang itu adalah tidak sepenuhnya streaming. Ini bukan masalah jika Anda bekerja dengan sedikit elemen dalam urutan Anda. Saya membutuhkan solusi baru ketika saya mulai bekerja dengan 100.000+ elemen dalam urutan saya.
Solusi berikut jauh lebih kompleks (dan lebih banyak kode!), Tetapi sangat efisien.
Nikmati!
sumber
Benang yang menarik. Untuk mendapatkan versi streaming Split / Partition, seseorang dapat menggunakan enumerator dan urutan hasil dari enumerator menggunakan metode ekstensi. Mengubah kode imperatif menjadi kode fungsional menggunakan hasil adalah teknik yang sangat ampuh.
Pertama, ekstensi enumerator yang mengubah hitungan elemen menjadi urutan malas:
Dan kemudian ekstensi yang dapat dihitung yang mempartisi urutan:
Hasil akhirnya adalah implementasi yang sangat efisien, streaming, dan malas yang mengandalkan kode yang sangat sederhana.
Nikmati!
sumber
Saya menggunakan ini:
sumber
Ini adalah efisiensi memori dan menunda eksekusi sebanyak mungkin (per batch) dan beroperasi dalam waktu linier O (n)
sumber
Ada banyak jawaban bagus untuk pertanyaan ini (dan sepupunya). Saya membutuhkan ini sendiri dan telah membuat solusi yang dirancang agar efisien dan toleran terhadap kesalahan dalam skenario di mana kumpulan sumber dapat diperlakukan sebagai daftar. Itu tidak menggunakan iterasi malas sehingga mungkin tidak cocok untuk koleksi dengan ukuran yang tidak diketahui yang mungkin menerapkan tekanan memori.
Saya telah melihat beberapa jawaban di seluruh keluarga pertanyaan ini yang menggunakan GetRange dan Math.Min. Tapi saya yakin secara keseluruhan ini adalah solusi yang lebih lengkap dalam hal pengecekan kesalahan dan efisiensi.
sumber
sumber
Jawaban Hebat, untuk skenario saya, saya menguji jawaban yang diterima, dan tampaknya itu tidak menjaga ketertiban. Ada juga jawaban bagus dari Nawfal yang menjaga ketertiban. Tetapi dalam skenario saya, saya ingin membagi sisanya dengan cara yang dinormalisasi, semua jawaban yang saya lihat menyebarkan sisanya atau di awal atau di akhir.
Jawaban saya juga membuat sisanya menyebar dengan cara yang lebih normal.
sumber
Jika urutan di bagian ini tidak terlalu penting, Anda dapat mencoba ini:
Namun ini tidak dapat dilemparkan ke IEnumerable <IEnumerable <int>> karena alasan tertentu ...
sumber
Ini kode saya, bagus dan pendek.
sumber
Ini adalah cara saya, membuat daftar item dan memecahkan baris demi kolom
sumber
Saya mencari perpecahan seperti yang ada string, jadi seluruh Daftar dipecah menurut beberapa aturan, tidak hanya bagian pertama, ini adalah solusi saya
sumber
Berikut ini sedikit perubahan untuk jumlah item, bukan jumlah bagian:
sumber
sumber
Baru saja menemukan utas ini, dan sebagian besar solusi di sini melibatkan penambahan item ke koleksi, yang secara efektif mewujudkan setiap halaman sebelum mengembalikannya. Ini buruk karena dua alasan - pertama jika halaman Anda besar, ada overhead memori untuk mengisi halaman, kedua ada iterator yang membuat catatan sebelumnya tidak valid saat Anda melanjutkan ke yang berikutnya (misalnya jika Anda menggabungkan DataReader dalam metode enumerator) .
Solusi ini menggunakan dua metode enumerator bersarang untuk menghindari kebutuhan untuk menyimpan item ke dalam cache sementara. Karena iterator luar dan dalam melintasi enumerator yang sama, mereka selalu berbagi enumerator yang sama, jadi penting untuk tidak memajukan yang luar sampai Anda selesai memproses halaman saat ini. Meskipun demikian, jika Anda memutuskan untuk tidak mengulang sepanjang halaman saat ini, saat Anda pindah ke halaman berikutnya, solusi ini akan beralih maju ke batas halaman secara otomatis.
sumber