วิธีการแบนวัตถุที่ซ้อนกันด้วยนิพจน์ linq


125

ฉันพยายามทำให้วัตถุที่ซ้อนกันแบนราบเช่นนี้:

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

ผมขอยกตัวอย่าง นี่คือข้อมูลที่ฉันมี

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

ผลลัพธ์ที่ฉันกำลังมองหาคือรายการแบนต่อไปนี้:

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

ฉันจะทำสิ่งนี้ให้สำเร็จได้อย่างไร? ฉันสามารถทำได้ด้วยการเลือกใหม่แต่ฉันได้รับแจ้งว่า SelectMany จะเพียงพอ

คำตอบ:


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

ที่น่ากลัว !!! จะเกิดอะไรขึ้นถ้าฉันจะได้ผลลัพธ์เป็นวัตถุใหม่เช่น FlatBook {BookName, ChapterName, PageName}
abx78

2
@ abx78: เพียงแค่แก้ไขการเลือกครั้งสุดท้าย:.Select(p => new FlatBook(b.Name, c.Name, p.Name))
user7116

ขอบคุณพวกคุณนี่คือสิ่งที่ฉันต้องการ!
abx78

1
สิ่งนี้ให้ผลลัพธ์เหมือนกันหรือไม่? myBooks.SelectMany(b => b.Chapters).SelectMany(c => c.Pages).Select(p => b.Name + ", " + c.Name + ", " + p.Name);
โฮเมอ

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

สมมติว่าbooksเป็นรายชื่อหนังสือ:

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 แม้ว่าIEnumerable<Book>จะทำอะไรก็ไม่จำเป็นต้องมี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
แม้ว่าตัวอย่างโค้ดนี้อาจตอบคำถาม แต่ก็ขาดคำอธิบาย ในขณะนี้มันไม่ได้เพิ่มมูลค่าและหมายถึงการเปลี่ยนแปลงของการลดลง / ลบ โปรดเพิ่มคำอธิบายว่าอะไรคืออะไรและทำไมจึงเป็นวิธีแก้ปัญหาของ OP
58

0

ฉันพยายามทำสิ่งนี้เช่นกันและจากความคิดเห็นของ Yuriy และการยุ่งกับ linqPad ฉันมีสิ่งนี้ ..

โปรดทราบว่าฉันไม่มีหนังสือบทหน้าฉันมีบุคคล (หนังสือ) บริษัท บุคคล (บท) และ บริษัท (หน้า)

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

หรือ

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

เว็บไซต์อ้างอิงที่ฉันใช้: http://odetocode.com/blogs/scott/archive/2008/03/25/inner-outer-lets-all-join-together-with-linq.aspx

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.