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.

abx78
sumber

Jawaban:

199
myBooks.SelectMany(b => b.Chapters
    .SelectMany(c => c.Pages
        .Select(p => b.Name + ", " + c.Name + ", " + p.Name)));
Yuriy Faktorovich
sumber
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};
boca
sumber
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
                });
Madhukar Bhandari
sumber
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

Mastro
sumber