İç içe geçmiş nesneler linq ifadesi ile nasıl düzleştirilir


125

İç içe geçmiş nesneleri şu şekilde düzleştirmeye çalışıyorum:

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; }
}

Bir örnek vereyim. Bu sahip olduğum veriler

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

Aradığım sonuç şu düz liste:

"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"

Bunu nasıl başarabilirim? Bunu yeni bir seçki ile yapabilirdim ama bir SelectMany'nin yeterli olacağı söylendi.

Yanıtlar:


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

Müthiş !!! FlatBook {BookName, ChapterName, PageName} gibi yeni bir nesne ile sonuçlanırsam ne olur?
abx78

2
@ abx78: sadece son seçimi değiştirin:.Select(p => new FlatBook(b.Name, c.Name, p.Name))
user7116

Teşekkürler çocuklar, ihtiyacım olan buydu!
abx78

1
bu aynı sonucu mu veriyor? myBooks.SelectMany(b => b.Chapters).SelectMany(c => c.Pages).Select(p => b.Name + ", " + c.Name + ", " + p.Name);
Homer

1
@Mastro how aboutmyBooks.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

booksBir Kitap Listesi olduğunu varsayarsak :

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, her IEnumerable<Book>ne kadar yapacak olsa da , bir List<Book>.
user7116

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

7
Bu kod örneği soruyu yanıtlasa da açıklamadan yoksundur. Şu an olduğu gibi, hiçbir değer katmaz ve olumsuz oylama / silinme değişimine dayanır. Lütfen neyin işe yaradığı ve neden OP problemi için bir çözüm olduğuna dair bir açıklama ekleyin.
oɔɯǝɹ

0

Ben de bunu yapmaya çalışıyordum ve Yuriy'in yorumlarına ve linqPad ile uğraşmasına dayanarak bu var ..

Kitaplarım, bölümlerim, sayfalarım olmadığını, şahsım (kitaplar), şirketKişimi (bölümler) ve şirketlerim (sayfalar) olmadığını unutmayın.

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
                           };

veya

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
         }
   )

Kullandığım referans sitesi: http://odetocode.com/blogs/scott/archive/2008/03/25/inner-outer-lets-all-join-together-with-linq.aspx

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.