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あるIQuerableILookupない
マグナス

5
GroupByはリストを列挙しませんToLookupはToList / ToArrayと同じ方法でリストを列挙します
Aducci

3
重複しているとされる質問は、GroupByではなくIGroupingおよびToLookupではなくILookupに関するものであるため、これを再開するために指定しました。それらの違いは、これらの違いとは異なります。これは、質問間の回答の違いから明らかです。
Sam

1
それらの両方が作成しLookupますが、GroupBy結果が列挙されたときに、それを作成しreferencesource.microsoft.com/#System.Core/System/Linq/...
Slai

回答:


175

なぜGroupByに迷惑をかけるのですか?なぜ存在する必要があるのですか?

10億行あるリモートデータベーステーブルを表すオブジェクトでToLookupを呼び出すとどうなりますか?

10億行がネットワーク経由で送信され、ローカルでルックアップテーブルを作成します。

このようなオブジェクトでGroupByを呼び出すとどうなりますか?

クエリオブジェクトが作成されます。物語の終わり。

そのクエリオブジェクトが列挙されると、テーブルの分析がデータベースサーバーで実行され、グループ化された結果がオンデマンドで一度に数回送信されます。

論理的には同じものですが、それぞれのパフォーマンスへの影響は完全に異なります。ToLookupを呼び出すと、現在、グループごとに整理されたすべてのもののキャッシュが必要になります。GroupByの呼び出しは、「「グループで整理すると、これらはどのように見えるのか」という質問を表すオブジェクトを構築しています」を意味します。


6
ポスターは、IQueryable<T>表現を明確に対象とするものではありません。あなたの答えはその状況をカバーしていますが、それが単なるol IEnumerable<T>(LINQ-to-Objects)である場合、どちらか一方を他方で使用する理由がないように思えることがあります。 そうでIQueryable<T>なく、LINQ-to-Objectsの場合です。
casperOne 2012

21
@casperOne:私の考えを理解できなかったと思います。LINQ-to-objectsの場合でも、GroupByを呼び出してもコレクションは反復されません。(Aducciがあなたが削除した答えで指摘したように。)それは根本的な違いです。
Eric Lippert

12
@EricLippert:しかし、それは実装の副作用にすぎませんか、それとも、実装にどのような変更が加えられても、ToLookupを呼び出すと、列挙型が反復されることが保証されますか?

9
@ウィル:あなたは素晴らしい点を作ります。ドキュメントは、ToLookupが「熱心」であることを保証しません。それはおそらくそれに注意すべきです。
Eric Lippert、2012

10
熱意はそれを説明します。「ToMetaType」という言葉は熱意を意味すると思います。それは明らかに実装次第です。他の「To」はすべて熱心です(ToList、ToArray、ToDictionary)。みんなありがとう。
シュロモ2012

98

簡単なLINQの世界の言葉で:

  • ToLookup() -即時実行
  • GroupBy() -遅延実行

17

2つは似ていますが、異なるシナリオで使用されます。.ToLookup()既にすべてのグループ(ただしグループのコンテンツではない)が熱心に読み込まれている、すぐに使用できるオブジェクトを返します。一方、.GroupBy()遅延して読み込まれたグループのシーケンスを返します。

LINQプロバイダーが異なれば、グループの積極的かつ遅延的なロードの動作が異なる場合があります。LINQ-to-Objectの場合、ほとんど違いはありませんが、LINQ-to-SQL(またはLINQ-to-EFなど)では、グループ化操作はクライアントではなくデータベースサーバーで実行されるため、 (HAVING句を生成する)グループキーで追加のフィルタリングを行い、すべてではなく一部のグループのみを取得します。.ToLookup()すべてのアイテムが熱心にグループ化されているため、このようなセマンティクスは許可されません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.