LINQ Group By menjadi Obyek Kamus

161

Saya mencoba menggunakan LINQ untuk membuat Dictionary<string, List<CustomObject>>dari List<CustomObject>. Saya bisa membuatnya bekerja menggunakan "var", tetapi saya tidak ingin menggunakan tipe anonim. Inilah yang saya miliki

var x = (from CustomObject o in ListOfCustomObjects
      group o by o.PropertyName into t
      select t.ToList());

Saya juga telah mencoba menggunakan Cast<>()dari perpustakaan LINQ sekali saya miliki x, tapi saya mendapatkan masalah kompilasi yang hasilnya menjadi pemain yang tidak valid.

Atari2600
sumber
Bagaimana jika Anda mencoba var x = (dari CustomObject o di grup ListOfCustomObjects o oleh o.PropertyName ke t pilih t) .ToList ();
esastincy
44
Apakah ada alasan mengapa Anda perlu melakukan ini daripada menggunakan ToLookup, yang dirancang untuk ini?
Jon Skeet
1
Jon, bisakah Anda memposting contoh cara kerja ToLookup dalam situasi ini? Saya tidak terbiasa dengan metode LINQ itu.
Atari2600
8
@JonSkeet Kamu luar biasa! (Maksudku, semua orang sudah tahu itu, tapi tetap saja.) Alasan aku tidak berencana menggunakan ToLookup adalah karena aku belum pernah mendengarnya sampai sekarang. Sekarang saya tahu!
neminem
1
Demi kelengkapan saja, menggunakan vartidak menggunakan tipe "anonim", itu menggunakan tipe "implisit". Tipe anonim adalah kelas baru yang dibuat oleh kompiler untuk menangani konstruksi new { thing = "stuff" };. Jenis implisit adalah kelas yang ada, varhanya cara yang mudah untuk referensi mereka ketika variabel ditugaskan segera, tipe variabel dapat disimpulkan dari jenis objek yang ditugaskan padanya. Anda bahkan dapat secara implisit mengetik variabel yang merujuk pada tipe anonim, yaitu:var a = new { thing = "stuff" };
Michael Blackburn

Jawaban:

350
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToDictionary(g => g.Key, g => g.ToList());
Yuriy Faktorovich
sumber
6
Kecuali jika Anda memerlukan properti dari 'CustomObject' sebagai nilai daftar (tidak ditampilkan dalam jawaban ini) ada baiknya memeriksa kodelitasnya komentar Jon Skeet untuk pertanyaan yang merekomendasikan ToLookup ().
Shaun
3
ini adalah cara untuk melakukannya jika hasil yang tidak dapat diubah diinginkan. ToLookup tidak dapat diubah.
Amit
1
2 Cents saya (hanya karena itu membuat saya berjuang selama satu jam :)): ketika mengelompokkan berdasarkan properti, pastikan Properti MEMILIKI nilainya! Kalau tidak, metode-Todict gagal menghasilkan kunci (setidaknya untuk String-Properties ...) :)
dba
.GroupBy(o => o.PropertyName).ToDictionary(g => g.Key, g => g.ToList())Ini bisa menjadi bagian dari ekstensi ekstensi Linq. jadi kita hanya perlu melakukan.ToDictionary(o=>o.PropertyName)
Jaider
3
@Jaider, sudah ada fungsi seperti itu: ganti saja ToDictionarydengan ToLookup.
Robert Synoradzki
19

Saya tidak dapat mengomentari @Michael Blackburn, tetapi saya kira Anda mendapatkan downvote karena GroupBy tidak diperlukan dalam kasus ini.

Gunakan seperti:

var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]

Selain itu, saya telah melihat ini berkinerja lebih baik daripada ketika menggunakan GroupBy (). ToDictionary ().

RuudvK
sumber
Saya melakukan transliterasi, tidak menanggapi pertanyaan dengan cara sebaik mungkin.
Michael Blackburn
1

Untuk @ atari2600, inilah yang akan terlihat seperti jawaban menggunakan ToLookup dalam sintaks lambda:

var x = listOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToLookup(customObject => customObject);

Pada dasarnya, dibutuhkan IGrouping dan mewujudkannya untuk Anda ke dalam kamus daftar, dengan nilai-nilai PropertyName sebagai kuncinya.

Michael Blackburn
sumber
Mengapa downvote? Apakah ini tidak akurat / menjawab pertanyaan?
Michael Blackburn
1
Jika Anda melewatkannya, @RuudvK menyebutkan dalam jawabannya bahwa ia mencurigai downvote adalah karena GroupBy tidak perlu. ToLookupmemiliki kelebihan yang akan menyelesaikan pekerjaan.
Jeff B
Saya melewatkan respons itu, terima kasih telah memberi tag saya. Masuk akal, pengelompokan secara sintaksis tidak perlu, saya hanya meninggalkannya untuk membuat transisi dari sintaks kueri ke metode sintaks lebih jelas.
Michael Blackburn
GroupBy (kelebihan dengan hanya satu parameter) mengembalikan IEnumerable <IGrouping <TKey, TSource >> ToLookup berikutnya kemudian mengubahnya menjadi jenis yang cukup rumit yang bahkan tidak mirip dengan IDictionary <TKey, IList <TSource>> hanya ToLookup mengembalikan tipe yang tepat.
xtofs
-1

Berikut ini bekerja untuk saya.

var temp = ctx.Set<DbTable>()
  .GroupBy(g => new { g.id })
  .ToDictionary(d => d.Key.id);
Leo Barbas
sumber