Tại sao ToLookup và GroupBy khác nhau?


111

.ToLookup<TSource, TKey>trả về một ILookup<TKey, TSource>. ILookup<TKey, TSource>cũng thực hiện giao diện IEnumerable<IGrouping<TKey, TSource>>.

.GroupBy<TSource, TKey>trả về một IEnumerable<IGrouping<Tkey, TSource>>.

ILookup có thuộc tính trình lập chỉ mục tiện dụng, vì vậy nó có thể được sử dụng theo cách giống như từ điển (hoặc giống như tra cứu), trong khi GroupBy thì không. GroupBy không có trình chỉ mục là một điều khó khăn khi làm việc với; khá nhiều cách duy nhất để bạn có thể tham chiếu đối tượng trả về là lặp qua nó (hoặc sử dụng một phương thức mở rộng LINQ khác). Nói cách khác, bất kỳ trường hợp nào mà GroupBy hoạt động, ToLookup cũng sẽ hoạt động.

Tất cả những điều này khiến tôi đặt ra câu hỏi tại sao tôi lại bận tâm đến GroupBy? Tại sao nó phải tồn tại?


7
GroupByIQuerable, ILookupkhông được
Magnus

5
GroupBy không liệt kê danh sách ToLookup liệt kê nó theo cùng một cách ToList / ToArray
Aducci

3
Tôi đã đề cử điều này để mở lại vì câu hỏi mà nó bị cho là trùng lặp là về IGrouping chứ không phải GroupByILookup hơn là ToLookup . Sự khác biệt giữa những cái đó khác với sự khác biệt giữa những cái này. Điều này phải rõ ràng từ sự khác biệt trong câu trả lời giữa các câu hỏi.
Sam

1
cả trong số họ tạo ra một Lookup, nhưng GroupBytạo ra nó khi kết quả được liệt kê referencesource.microsoft.com/#System.Core/System/Linq/...
Slai

Câu trả lời:


175

tại sao tôi lại bận tâm đến GroupBy? Tại sao nó phải tồn tại?

Điều gì sẽ xảy ra khi bạn gọi ToLookup trên một đối tượng đại diện cho một bảng cơ sở dữ liệu từ xa với hàng tỷ hàng trong đó?

Tỷ hàng được gửi qua dây và bạn xây dựng bảng tra cứu cục bộ.

Điều gì xảy ra khi bạn gọi GroupBy trên một đối tượng như vậy?

Một đối tượng truy vấn được xây dựng; kết thúc câu chuyện.

Khi đối tượng truy vấn đó được liệt kê thì việc phân tích bảng được thực hiện trên máy chủ cơ sở dữ liệu và các kết quả được nhóm lại được gửi lại theo yêu cầu một vài kết quả tại một thời điểm.

Về mặt logic, chúng giống nhau nhưng hàm ý về hiệu suất của chúng hoàn toàn khác nhau. Gọi ToLookup có nghĩa là tôi muốn một bộ nhớ cache của toàn bộ nội dung ngay bây giờ được sắp xếp theo nhóm . Gọi GroupBy có nghĩa là "Tôi đang xây dựng một đối tượng để đại diện cho câu hỏi 'những thứ này sẽ như thế nào nếu tôi tổ chức chúng theo nhóm?'"


6
Người đăng không nhắm mục tiêu cụ thể một hình ảnh IQueryable<T>đại diện. Câu trả lời của bạn bao gồm tình huống đó, nhưng khi nó chỉ đơn giản là IEnumerable<T>(LINQ-to-Objects), có vẻ như không có lý do gì để sử dụng cái này thay cho cái kia, đó là điều tôi tin rằng @Shlomo đang cố gắng đạt được. Không phảiIQueryable<T> trường hợp, mà là trường hợp LINQ-to-Objects.
casperOne

21
@casperOne: Tôi nghĩ bạn đã không hiểu quan điểm của tôi. Ngay cả trong trường hợp LINQ-to-objects, việc gọi GroupBy vẫn không lặp lại bộ sưu tập. (Như Aducci đã chỉ ra trong câu trả lời mà bạn đã xóa.) Đó là một sự khác biệt cơ bản.
Eric Lippert

12
@EricLippert: Nhưng liệu đó có phải chỉ là một tác dụng phụ của việc triển khai hay nó được đảm bảo rằng liệt kê sẽ được lặp lại khi bạn gọi ToLookup, bất kể việc triển khai có thay đổi gì không?

9
@Will: Bạn thực hiện một điểm xuất sắc; tài liệu không đảm bảo rằng ToLookup là "háo hức". Nó có lẽ nên lưu ý rằng.
Eric Lippert

10
Sự háo hức giải thích điều đó. Ngôn ngữ của 'ToMetaType' tôi nghĩ ngụ ý sự háo hức; mặc dù nó rõ ràng là để thực hiện. Các 'To khác đều háo hức (ToList, ToArray, ToDictionary). Cảm ơn các bạn.
Shlomo

98

Nói một cách đơn giản từ LINQ-world:

  • ToLookup() - thực hiện ngay lập tức
  • GroupBy() - thực hiện hoãn lại

17

Cả hai tương tự nhau, nhưng được sử dụng trong các trường hợp khác nhau. .ToLookup()trả về một đối tượng sẵn sàng sử dụng đã có tất cả các nhóm (nhưng không phải nội dung của nhóm) được tải sẵn sàng. Mặt khác, .GroupBy()trả về một chuỗi các nhóm được tải chậm.

Các nhà cung cấp LINQ khác nhau có thể có các hành vi khác nhau đối với việc tải các nhóm một cách háo hức và lười biếng. Với LINQ-to-Object, nó có thể tạo ra một chút khác biệt, nhưng với LINQ-to-SQL (hoặc LINQ-to-EF, v.v.), hoạt động nhóm được thực hiện trên máy chủ cơ sở dữ liệu thay vì máy khách, và vì vậy bạn có thể muốn để thực hiện một phép lọc bổ sung trên khóa nhóm (tạo ra một HAVINGmệnh đề) và sau đó chỉ lấy một số nhóm thay vì tất cả chúng. .ToLookup()sẽ không cho phép những ngữ nghĩa như vậy vì tất cả các mục đều được nhóm một cách háo hức.

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.