Nhóm LINQ thành một đối tượng từ điển


161

Tôi đang cố gắng sử dụng LINQ để tạo Dictionary<string, List<CustomObject>>từ a List<CustomObject>. Tôi có thể làm điều này hoạt động bằng cách sử dụng "var", nhưng tôi không muốn sử dụng các loại ẩn danh. Đây là những gì tôi có

var x = (from CustomObject o in ListOfCustomObjects
      group o by o.PropertyName into t
      select t.ToList());

Tôi cũng đã thử sử dụng Cast<>()từ thư viện LINQ khi tôi có x, nhưng tôi gặp các vấn đề biên dịch do ảnh hưởng của nó là một dàn diễn viên không hợp lệ.


Điều gì sẽ xảy ra nếu bạn thử var x = (từ CustomObject o trong ListOfCustomObjects nhóm o by o.PropertyName vào t chọn t) .ToList ();
esastincy

44
Có bất kỳ lý do tại sao bạn cần phải làm điều này hơn là sử dụng ToLookup, được thiết kế cho việc này?
Jon Skeet

1
Jon, bạn có thể vui lòng gửi một ví dụ về cách ToLookup hoạt động trong tình huống này không? Tôi không quen thuộc với phương pháp LINQ đó.
Atari2600

8
@JonSkeet Bạn thật tuyệt vời! (Ý tôi là, mọi người đều biết điều đó rồi, nhưng vẫn vậy.) Lý do tôi không định sử dụng ToLookup là vì tôi chưa bao giờ nghe về nó cho đến bây giờ. Bây giờ tôi biết!
neminem

1
Để hoàn thiện hơn, sử dụng varkhông sử dụng loại "ẩn danh", đó là sử dụng loại "ẩn". Các kiểu ẩn danh là các lớp mới được tạo bởi trình biên dịch để xử lý việc xây dựng new { thing = "stuff" };. Các kiểu ẩn là các lớp hiện có, varchỉ là một cách thuận tiện để tham chiếu chúng khi biến được gán ngay lập tức, loại biến có thể được suy ra từ loại đối tượng được gán cho nó. Bạn thậm chí có thể ngầm định nhập một biến tham chiếu một loại ẩn danh, tức là:var a = new { thing = "stuff" };
Michael Blackburn

Câu trả lời:


350
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToDictionary(g => g.Key, g => g.ToList());

6
Trừ khi bạn cần một thuộc tính từ 'CustomObject' làm giá trị danh sách (không được hiển thị trong câu trả lời này), bạn nên kiểm tra nhận xét của Jon Skeet về câu hỏi giới thiệu ToLookup ().
Shaun

3
đây là cách để làm điều đó nếu muốn có kết quả không thay đổi. ToLookup là bất biến.
Amit

1
2 Cents của tôi (chỉ vì nó khiến tôi phải vật lộn trong một giờ :)): khi nhóm theo một tài sản, hãy đảm bảo Tài sản ĐÃ có giá trị! Mặt khác, phương thức Todict không tạo được khóa (đối với Thuộc tính chuỗi ít nhất là ...) :)
dba

.GroupBy(o => o.PropertyName).ToDictionary(g => g.Key, g => g.ToList())Đây có thể là một phần của thư viện Linq mở rộng. vì vậy chúng tôi chỉ phải làm.ToDictionary(o=>o.PropertyName)
Jaider

3
@Jaider, đã có chức năng như vậy: chỉ cần thay thế ToDictionarybằng ToLookup.
Robert Synoradzki

19

Tôi không thể nhận xét về @Michael Blackburn, nhưng tôi đoán bạn đã tải xuống vì GroupBy không cần thiết trong trường hợp này.

Sử dụng nó như:

var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]

Ngoài ra, tôi đã thấy cách này hiệu quả hơn so với khi sử dụng GroupBy (). ToDipedia ().


Tôi đã thực hiện phiên âm, không trả lời câu hỏi theo cách tốt nhất có thể.
Michael Blackburn

1

Đối với @ atari2600, đây là câu trả lời sẽ như thế nào khi sử dụng ToLookup theo cú pháp lambda:

var x = listOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToLookup(customObject => customObject);

Về cơ bản, nó lấy IGrouping và cụ thể hóa nó cho bạn vào một từ điển danh sách, với các giá trị của PropertyName làm khóa.


Tại sao một downvote? Đây có phải là không chính xác / trả lời câu hỏi?
Michael Blackburn

1
Trong trường hợp bạn bỏ lỡ nó, @RuudvK đã đề cập trong câu trả lời của anh ấy rằng anh ấy nghi ngờ downvote là vì GroupBy là không cần thiết. ToLookupcó một quá tải sẽ hoàn thành công việc.
Jeff B

Tôi đã bỏ lỡ phản hồi đó, cảm ơn vì đã gắn thẻ tôi. Có nghĩa là, Nhóm là không cần thiết về mặt cú pháp, tôi chỉ để nó vào để làm cho việc chuyển từ cú pháp truy vấn sang cú pháp phương thức rõ ràng hơn.
Michael Blackburn

GroupBy (quá tải chỉ với một tham số) trả về IEnountable <IGrouping <TKey, TSource >> sau đó ToLookup sau đó biến nó thành một loại khá phức tạp thậm chí không giống với IDadata <TKey, IList <TSource >> chỉ là ToLookup trả về loại thích hợp.
xtofs

-1

Sau đây làm việc cho tôi.

var temp = ctx.Set<DbTable>()
  .GroupBy(g => new { g.id })
  .ToDictionary(d => d.Key.id);
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.