สร้างพจนานุกรมในรายการด้วยการจัดกลุ่ม


106

ฉันมีวัตถุต่อไปนี้ในรายการ:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}

ตอนนี้ฉันต้องการสร้างพจนานุกรมต่อไปนี้จากมัน:

Dictionary<int, List<DemoClass>>

ฉันต้องการจัดกลุ่มList<DemoClass>ตามพร็อพเพอร์ตี้GroupKeyแต่ฉันไม่เข้าใจวิธีการดำเนินการนี้และความช่วยเหลือบางอย่าง

หลังจากคิดสักนิดฉันก็บรรลุพฤติกรรมที่ต้องการด้วย:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

แต่มีวิธีทำให้สิ่งนี้เป็นคำสั่งเดียวหรือไม่?

คำตอบ:



198

เพียงเพื่อให้ข้อเสนอแนะของ mquander เป็นรูปธรรม:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

คุณจะทำให้สั้นลงถ้าคุณใช้ชื่อตัวแปรที่สั้นลงด้วย :)

อย่างไรก็ตามฉันขอแนะนำว่าLookupอาจเหมาะสมกว่าหรือไม่ โดยพื้นฐานแล้วการค้นหาเป็นพจนานุกรมจากคีย์ไปยังIEnumerable<T>- เว้นแต่คุณต้องการค่าเป็นรายการจริงๆมันจะทำให้โค้ดสั้นลง (และมีประสิทธิภาพมากขึ้น) ด้วยการเรียกToLookup :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);

1
ฉันคิดว่าการค้นหาทำงานได้ไม่ดีเมื่อเทียบกับพจนานุกรมที่สร้างขึ้นในสภาพแวดล้อมระยะยาวเนื่องจากสร้างผลลัพธ์ใหม่สำหรับทุกคำขอ ... โปรดแก้ไขฉันถ้าฉันผิด!
Andreas Niedermair

ไม่มันสร้างการค้นหาทั้งหมด โดยทั่วไป ToXXX ไม่ใช้การดำเนินการรอการตัดบัญชี
Jon Skeet

1
(คุณอาจกำลังนึกถึงการจัดกลุ่มซึ่งจะถูกเลื่อนออกไป)
Jon Skeet

1
ถ้าฉันไม่อาฆาตแค้นฉันจะโหวตให้คุณ มาเพื่อ Linq อยู่สำหรับโครงสร้างข้อมูลที่ฉันไม่เคยได้ยินมาก่อน!
Chris McCall

2
@sasikt: แบบจำลองคือคุณสามารถค้นหาอะไรก็ได้และคุณจะได้รับคอลเลกชันที่ว่างเปล่าหากไม่มีคีย์ ซึ่งมักจะมีประโยชน์มากกว่าวิธี TryGetValue, IMO
Jon Skeet

6

คุณทำซับไว้แล้ว เพียงใส่ToDictionaryท้ายบรรทัดแรกของคุณ ถ้าคุณต้องการให้สั้นลงให้ใช้ไวยากรณ์ขององค์ประกอบที่ใช้งานได้แทนไวยากรณ์ของแบบสอบถาม


3

ฉันจะออกจากหัวข้อเล็กน้อยที่นี่ แต่ฉันมาที่หัวข้อนี้เนื่องจากฉันกำลังมองหาวิธีสร้างพจนานุกรมของพจนานุกรมใน Linq และการสนทนาที่นี่นำฉันไปสู่คำตอบ ...

คุณสามารถใช้ linq เพื่อสร้างพจนานุกรมหลายระดับซึ่งมีประโยชน์สำหรับสถานการณ์ที่คุณมีคีย์หรือมิติข้อมูลมากกว่า 1 รายการที่คุณต้องการค้นหา เคล็ดลับคือการสร้างการจัดกลุ่มแล้วแปลงเป็นพจนานุกรมดังนี้:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

สามารถใช้แบบสอบถามผลลัพธ์ดังนี้:

 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

หวังว่านี่จะเป็นประโยชน์กับคนอื่น ๆ ที่ต้องการคำถามประเภทนี้

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