Tạo từ điển trên danh sách bằng cách nhóm


106

Tôi có đối tượng sau trong danh sách:

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

Bây giờ, tôi muốn tạo từ điển sau từ nó:

Dictionary<int, List<DemoClass>>

Tôi muốn nhóm các List<DemoClass>thuộc tính GroupKey, nhưng tôi không hiểu điều này được thực hiện như thế nào và một số trợ giúp.

Sau khi suy nghĩ một chút, tôi đã đạt được hành vi cần thiết với:

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());

nhưng, có cách nào để biến điều này thành một câu lệnh duy nhất không?

Câu trả lời:


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

Cái này sẽ hoạt động !!!


198

Chỉ để làm cho đề xuất của mquander cụ thể:

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

Tất nhiên, bạn sẽ làm cho nó ngắn hơn nếu bạn cũng sử dụng các tên biến ngắn hơn :)

Tuy nhiên, tôi có thể gợi ý rằng Tra cứu có thể thích hợp hơn không? Tra cứu về cơ bản là một từ điển từ khóa đến khóa IEnumerable<T>- trừ khi bạn thực sự cần các giá trị dưới dạng danh sách, nó làm cho mã ngắn hơn (và hiệu quả hơn) với lệnh gọi ToLookup :

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

1
tôi nghĩ rằng tra cứu hoạt động không tốt, so với từ điển được xây dựng, trong môi trường dài hạn, do nó tạo ra kết quả mới cho mọi yêu cầu ... vui lòng sửa cho tôi, nếu tôi sai!
Andreas Niedermair

Không, nó tạo ra toàn bộ tra cứu. Nói chung, ToXXX không sử dụng thực thi hoãn lại.
Jon Skeet

1
(Bạn có thể đang nghĩ đến Phân nhóm, điều này thực sự bị hoãn lại.)
Jon Skeet

1
Nếu tôi không cay cú như vậy, tôi sẽ bỏ phiếu cho bạn. Đến với Linq, ở lại với cấu trúc dữ liệu mà tôi chưa bao giờ nghe nói đến!
Chris McCall

2
@sasikt: Mô hình là bạn có thể tra cứu bất cứ thứ gì , và bạn chỉ nhận được một bộ sưu tập trống nếu khóa không tồn tại. Điều đó thường hữu ích hơn phương pháp TryGetValue, IMO.
Jon Skeet

6

Bạn đã làm cho nó một lớp lót. Chỉ cần đặt ToDictionaryở cuối dòng đầu tiên của bạn. Nếu bạn muốn nó ngắn hơn, hãy sử dụng cú pháp thành phần chức năng thay vì cú pháp truy vấn.


3

Tôi hơi lạc đề ở đây, nhưng tôi đến chủ đề này vì tôi đang tìm cách tạo một từ điển của từ điển trong Linq, và cuộc trò chuyện ở đây dẫn tôi đến câu trả lời ...

Bạn có thể sử dụng linq để tạo từ điển nhiều cấp, rất hữu ích cho các trường hợp bạn có nhiều hơn 1 khóa hoặc thứ nguyên mà bạn muốn tìm kiếm. Bí quyết là tạo một nhóm và sau đó chuyển nó thành từ điển, như sau:

  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)

Truy vấn kết quả có thể được sử dụng như sau:

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

Hy vọng điều này sẽ hữu ích cho bất kỳ ai khác cần loại truy vấn này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.