Чому ToLookup та GroupBy відрізняються?


111

.ToLookup<TSource, TKey>повертає ILookup<TKey, TSource>. ILookup<TKey, TSource>також реалізує інтерфейс IEnumerable<IGrouping<TKey, TSource>>.

.GroupBy<TSource, TKey>повертає IEnumerable<IGrouping<Tkey, TSource>>.

ILookup має зручну властивість індексатора, тому його можна використовувати в словниковому (або схожому на пошук) способі, тоді як GroupBy не може. GroupBy без індексатора - це біль, з якою працювати; майже єдиним способом ви можете посилатися на об'єкт, що повертається, - прокручуючи його (або використовуючи інший метод розширення LINQ). Іншими словами, у будь-якому випадку, коли GroupBy працює, також працюватиме ToLookup.

Все це залишає у мене питання, чому я б коли-небудь турбував GroupBy? Чому воно має існувати?


7
GroupByЄ IQuerable, ILookupні
Магнус

5
GroupBy не перераховує список ToLookup перераховує його так само, як ToList / ToArray
Aducci

3
Я висунув це для повторного відкриття, оскільки питання, яке його нібито є дублікатом, стосується IGrouping, а не GroupBy та ILookup, а не ToLookup . Відмінності між ними відрізняються від відмінностей між ними. Це повинно бути видно з відмінностей у відповідях між питаннями.
Сем

1
обидва вони створюють Lookup, але GroupByстворює його, коли результат перераховується referenceource.microsoft.com/#System.Core/System/Linq/…
Slai

Відповіді:


175

чому я коли-небудь морочився з GroupBy? Чому воно має існувати?

Що відбувається, коли ви викликаєте ToLookup на об'єкті, що представляє віддалену таблицю бази даних, яка містить мільярд рядків?

Мільярд рядків надсилається по дроту, і ви будуєте таблицю пошуку локально.

Що відбувається, коли ви дзвоните GroupBy на такий об’єкт?

Побудований об’єкт запиту; кінець історії.

Коли цей об'єкт запиту перераховується, аналіз таблиці проводиться на сервері баз даних, і згруповані результати надсилаються на вимогу декілька за один раз.

Логічно вони однакові, але наслідки для продуктивності кожного абсолютно різні. Виклик ToLookup означає, що я хочу кеш усієї справи зараз організованої групою . Виклик GroupBy означає "Я будую об'єкт для представлення питання" як би виглядали ці речі, якби я організував їх за групою? "


6
Плакат конкретно не націлений на IQueryable<T>представлення. Ваша відповідь охоплює таку ситуацію, але коли це просто просто IEnumerable<T>(LINQ-to-Objects), може здатися, що немає причин використовувати один над іншим, що я вважаю, що @Shlomo намагається досягти. Чи неIQueryable<T> справа, але справа LINQ до об'єктів.
casperOne

21
@casperOne: Я думаю, ви не зрозуміли мою думку. Навіть у випадку LINQ до об'єктів виклик GroupBy все ще не повторює колекцію. (Як зазначив Адуччі у відповіді, яку ви видалили.) Це принципова різниця.
Ерік Ліпперт

12
@EricLippert: Але це лише побічний ефект від впровадження або гарантується, що перелік буде повторений, коли ви зателефонуєте в ToLookup, незалежно від того, які зміни будуть внесені до реалізації?

9
@Will: Ви чудово ставитесь до справи; документація не гарантує, що ToLookup "прагне". Мабуть, це слід зазначити.
Ерік Ліпперт

10
Гострота пояснює це. Мова "ToMetaType", на мою думку, передбачає прагнення; хоча це явно залишається за реалізацією. Інші "Команди" всі охочі (ToList, ToArray, ToDictionary). Спасибі, хлопці.
Шломо

98

Простими словами LINQ-світу:

  • ToLookup() - негайне виконання
  • GroupBy() - відкладене виконання

17

Два подібні, але використовуються в різних сценаріях. .ToLookup()повертає готовий до використання об’єкт, у якому вже охоче завантажуються всі групи (але не вміст групи). З іншого боку, .GroupBy()повертає ледачу завантажену послідовність груп.

Різні постачальники LINQ можуть мати різну поведінку для нетерплячого та ледачого навантаження груп. З LINQ-to-Object це, мабуть, має незначне значення, але з LINQ-SQL (або LINQ-to-EF тощо) операція групування виконується на сервері баз даних, а не на клієнті, і тому ви можете захотіти зробити додаткову фільтрацію на груповому ключі (яка генерує HAVINGпункт), а потім отримати лише деякі групи замість усіх. .ToLookup()не дозволить проводити таку семантику, оскільки всі елементи охоче групуються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.