SelectとSelectManyの違い
LinqのSelectとSelectManyの違いについて。
public static IEnumerable<TResult> Select<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, TResult> selector) // ------- public static IEnumerable<TResult> SelectMany<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) // --------------------
これらの違いは、引数に指定する関数selectorの戻り値の型が、TResultかIEnumerable<TResult>かだけである。
Selectは、次のように動作する。
- Selectは、sourceの各要素を引数としてselectorを繰り返し呼び出す。
- selectorは、渡された要素を加工して返す。渡された要素の型はTSource、返す要素の型はTResult。
- Selectは、返された要素をまとめてIEnumerable<TResult>として返す。
これに対して、
- SelectManyは、sourceの各要素を引数としてselectorを繰り返し呼び出すところまでは同じ。
- selectorは、渡された要素から、ひとまとまりの要素を選択しIEnumerable<TResult>として返す。
- SelectManyは、返されたそれぞれのひとまとまりから各要素を取り出し、それらをまとめてIEnumerable<TResult>として返す。
これらのメソッドに、引数sourceとしてIEnumerable<IEnumerable<string>>型の値を、また引数selectorとして渡された引数をそのまま返す関数を使ってみる。
using System.Collections.Generic; using System.Linq; namespace SelectManySample { class Program { static void Main(string[] args) { IEnumerable<IEnumerable<string>> listOfArrayOfString = new List<string[]>() { new string[] { "1-1" }, new string[] { "2-1", "2-2" }, new string[] { "3-1", "3-2", "3-3" } }; IEnumerable<IEnumerable<string>> selectResult = listOfArrayOfString.Select(ReturnAsIs); IEnumerable<string> selectManyResult = listOfArrayOfString.SelectMany(ReturnAsIs); } static IEnumerable<string> ReturnAsIs(IEnumerable<string> arg) { return arg; } } }
Selectは、次のように動作する。
- Selectは、source { { "1-1" }, { "2-1", "2-2" }, { "3-1", "3-2", "3-3" } } の各要素 { "1-1" }, { "2-1", "2-2" }, { "3-1", "3-2", "3-3" } を、順にselectorに渡す。
- selectorは、それをそのまま返す。
- Selectは、返された要素をまとめて { { "1-1" }, { "2-1", "2-2" }, { "3-1", "3-2", "3-3" } } として返す。
これに対して、SelectManyは、
- selectorに渡すものとselectorが返すものは同じ。
- SelectManyは、返されたそれぞれのひとまとまり { "1-1" }, { "2-1", "2-2" }, { "3-1", "3-2", "3-3" } から各要素 "1-1", "2-1", "2-2", "3-1", "3-2", "3-3" を取り出し、それらをまとめて { "1-1", "2-1", "2-2", "3-1", "3-2", "3-3" } として返す。
Selectはデータ構造の形を変えない。これに対してSelectManyはコレクションを1つ展開して平坦にする。
Selectはコレクションの各要素の操作に使う。これに対して、SelectManyはコレクションのコレクションの操作に使う。具体的には、
- あるコレクションのそれぞれの要素から、操作対象となるコレクションを選択し、
- 必要に応じて、操作対象のコレクションの各要素を加工し、
- 加工した要素をひとまとめにして返す。