Bagaimana meratakan objek bersarang dengan ekspresi LINQ


125

Saya mencoba untuk meratakan objek bersarang seperti ini:

public class Book
{
    public string Name { get; set; }
    public IList<Chapter> Chapters { get; set; }
}

public class Chapter
{
    public string Name { get; set; }
    public IList<Page> Pages { get; set; }
}


public class Page
{
    public string Name { get; set; }
}

Izinkan saya memberi contoh. Ini adalah data yang saya miliki

Book: Pro Linq 
{ 
   Chapter 1: Hello Linq 
   {
      Page 1, 
      Page 2, 
      Page 3
   },
   Chapter 2: C# Language enhancements
   {
      Page 4
   },
}

Hasil yang saya cari adalah daftar datar berikut:

"Pro Linq", "Hello Linq", "Page 1"
"Pro Linq", "Hello Linq", "Page 2"
"Pro Linq", "Hello Linq", "Page 3"
"Pro Linq", "C# Language enhancements", "Page 4"

Bagaimana saya bisa mencapai ini? Saya dapat melakukannya dengan memilih baru tetapi saya telah diberitahu bahwa SelectMany sudah cukup.

Jawaban:


199
myBooks.SelectMany(b => b.Chapters
    .SelectMany(c => c.Pages
        .Select(p => b.Name + ", " + c.Name + ", " + p.Name)));

Luar biasa !!! Bagaimana jika saya akan mendapatkan hasil objek baru, seperti FlatBook {BookName, ChapterName, PageName}?
abx78

2
@ abx78: cukup ubah pilihan terakhir:.Select(p => new FlatBook(b.Name, c.Name, p.Name))
user7116

Terima kasih teman-teman, inilah yang saya butuhkan!
abx78

1
apakah ini menghasilkan hasil yang sama? myBooks.SelectMany(b => b.Chapters).SelectMany(c => c.Pages).Select(p => b.Name + ", " + c.Name + ", " + p.Name);
Homer

1
@Mastro bagaimana denganmyBooks.SelectMany(b => b.Chapters == null || !b.Chapters.Any()? new []{b.Name + " has no Chapters"} : b.SelectMany(c => c.Pages.Select(p => b.Name + ", " + c.Name + ", " + p.Name)));
Yuriy Faktorovich

50

Dengan asumsi booksadalah Daftar Buku:

var r = from b in books
    from c in b.Chapters
    from p in c.Pages
    select new {BookName = b.Name, ChapterName = c.Name, PageName = p.Name};

2
+1, meskipun semua IEnumerable<Book>akan dilakukan, tidak membutuhkan file List<Book>.
pengguna7116

2
myBooks.SelectMany(b => b.Chapters
    .SelectMany(c => c.Pages
        .Select(p => new 
                {
                    BookName = b.Name ,
                    ChapterName = c.Name , 
                    PageName = p.Name
                });

7
Meskipun contoh kode ini mungkin menjawab pertanyaan, namun kekurangan penjelasan. Seperti berdiri sekarang, ia tidak menambah nilai, dan merupakan perubahan menjadi downvoted / dihapus. Mohon ditambahkan penjelasan apa yang dimaksud dan mengapa ini merupakan solusi untuk masalah OP.
oɔɯǝɹ

0

Saya mencoba melakukan ini juga, dan dari komentar Yuriy dan mengotak-atik linqPad saya punya ini ..

Perhatikan bahwa saya tidak memiliki buku, bab, halaman, saya memiliki orang (buku), perusahaanPerson (bab) dan perusahaan (halaman)

from person in Person
                           join companyPerson in CompanyPerson on person.Id equals companyPerson.PersonId into companyPersonGroups
                           from companyPerson in companyPersonGroups.DefaultIfEmpty()
                           select new
                           {
                               ContactPerson = person,
                               ContactCompany = companyPerson.Company
                           };

atau

Person
   .GroupJoin (
      CompanyPerson, 
      person => person.Id, 
      companyPerson => companyPerson.PersonId, 
      (person, companyPersonGroups) => 
         new  
         {
            person = person, 
            companyPersonGroups = companyPersonGroups
         }
   )
   .SelectMany (
      temp0 => temp0.companyPersonGroups.DefaultIfEmpty (), 
      (temp0, companyPerson) => 
         new  
         {
            ContactPerson = temp0.person, 
            ContactCompany = companyPerson.Company
         }
   )

Situs referensi yang saya gunakan: http://odetocode.com/blogs/scott/archive/2008/03/25/inner-outer-lets-all-join-together-with-linq.aspx

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.