Saya menggunakan instruksi LINQ to Objects pada array yang dipesan. Operasi mana yang tidak harus saya lakukan untuk memastikan urutan array tidak berubah?
Saya menggunakan instruksi LINQ to Objects pada array yang dipesan. Operasi mana yang tidak harus saya lakukan untuk memastikan urutan array tidak berubah?
Jawaban:
Saya memeriksa metode System.Linq.Enumerable , membuang semua yang mengembalikan hasil non-IEnumerable. Saya memeriksa komentar masing-masing untuk menentukan bagaimana urutan hasil akan berbeda dari urutan sumber.
Mempertahankan Ketertiban sepenuhnya. Anda dapat memetakan elemen sumber dengan indeks ke elemen hasil
Mempertahankan Ketertiban. Elemen disaring atau ditambahkan, tetapi tidak dipesan ulang.
Hancurkan Pesanan - kami tidak tahu pesanan apa yang diharapkan terjadi.
Tetapkan Ulang Pesanan Secara Eksplisit - gunakan ini untuk mengubah urutan hasilnya
Mendefinisikan ulang Pesanan sesuai dengan beberapa aturan.
Sunting: Saya telah memindahkan Distinct to Preserving order berdasarkan pada implementasi ini .
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
Distinct
metode) hanya bermaksud mengatakan "tidak disortir", bukan "dalam urutan yang tidak terduga". Saya akan mengatakan Distinct
milik kategori penyaringan di atas, sama seperti Where
.
Apakah Anda benar-benar berbicara tentang SQL, atau tentang array? Dengan kata lain, apakah Anda menggunakan LINQ ke SQL atau LINQ ke Objek?
Operator LINQ to Objects tidak benar-benar mengubah sumber data asli mereka - mereka membangun urutan yang secara efektif didukung oleh sumber data. Satu-satunya operasi yang mengubah urutan adalah OrderBy / OrderByDescending / ThenBy / ThenByDescending - dan bahkan kemudian, itu stabil untuk elemen-elemen yang dipesan sama. Tentu saja, banyak operasi akan menyaring beberapa elemen, tetapi elemen yang dikembalikan akan berada dalam urutan yang sama.
Jika Anda mengonversi ke struktur data yang berbeda, mis. Dengan ToLookup atau ToDictionary, saya tidak yakin pesanan tetap dipertahankan pada saat itu - tetapi itu agak berbeda pula. (Namun, urutan pemetaan nilai untuk kunci yang sama dipertahankan untuk pencarian, saya yakin.)
GroupBy
diikuti oleh SelectMany
akan memberikan hasil yang dikelompokkan berdasarkan kunci, tetapi tidak dalam urutan kunci naik ... itu akan memberi mereka dalam urutan di mana kunci awalnya terjadi.
list<x> {a b c d e f g}
jika c, d, e semuanya memiliki kunci yang sama maka urutan yang dihasilkan akan berisi c, d, e di samping satu sama lain DAN dalam urutan c, d, e. Saya sepertinya tidak dapat menemukan jawaban berdasarkan kategori MS.
Jika Anda bekerja pada sebuah array, sepertinya Anda menggunakan LINQ-to-Objects, bukan SQL; Bisakah kamu mengkonfirmasi? Sebagian besar operasi LINQ tidak memesan ulang apa pun (output akan berada dalam urutan yang sama dengan input) - jadi jangan menerapkan jenis lain (OrderBy [Turun] / ThenBy [Turun]).
[sunting: seperti yang Jon jelaskan; LINQ umumnya membuat urutan baru , meninggalkan data asli sendirian]
Perhatikan bahwa memasukkan data ke Dictionary<,>
(ToDictionary) akan mengacak data, karena kamus tidak menghormati urutan pengurutan tertentu.
Tetapi hal yang paling umum (Pilih, Di Mana, Lewati, Ambil) harus baik-baik saja.
ToDictionary()
semata-mata tidak membuat janji tentang pesanan, tetapi dalam praktiknya mempertahankan urutan input (sampai Anda menghapus sesuatu dari itu). Saya tidak mengatakan mengandalkan ini, tetapi 'berebut' tampaknya tidak akurat.
Saya menemukan jawaban yang bagus dalam pertanyaan serupa yang merujuk pada dokumentasi resmi. Mengutipnya:
Untuk Enumerable
metode (LINQ untuk Objects, yang berlaku untuk List<T>
), Anda dapat mengandalkan urutan elemen dikembalikan oleh Select
, Where
atau GroupBy
. Ini bukan kasus untuk hal-hal yang secara inheren tidak teratur seperti ToDictionary
atau Distinct
.
Dari dokumentasi Enumerable.GroupBy :
The
IGrouping<TKey, TElement>
objek yang dihasilkan dalam urutan berdasarkan urutan unsur-unsur dalam sumber yang menghasilkan kunci pertama dari setiapIGrouping<TKey, TElement>
. Elemen-elemen dalam suatu pengelompokan dihasilkan dalam urutan kemunculannyasource
.
Ini tidak selalu benar untuk IQueryable
metode ekstensi (penyedia LINQ lainnya).
Sumber: Apakah Metode Enumerable LINQ Menjaga Urutan Relatif Unsur?
Pertanyaan di sini secara khusus mengacu pada LINQ-to-Objects.
Jika Anda menggunakan LINQ-to-SQL bukan tidak ada pesanan di sana kecuali Anda memaksakannya dengan sesuatu seperti:
mysqlresult.OrderBy(e=>e.SomeColumn)
Jika Anda tidak melakukan ini dengan LINQ-to-SQL, maka urutan hasil dapat bervariasi di antara kueri berikutnya, bahkan dari data yang sama, yang dapat menyebabkan bug yang terputus-putus.