射影操作
射影とは、オブジェクトを新しい形式に変換する操作のことを言います。この新しい形式は多くの場合、後で使用するプロパティだけで構成されたものになります。 射影を使用することで、各オブジェクトからビルドされる新しい型を構築することができます。 プロパティを射影し、それに対して数値演算関数を実行することができます。 また、元のオブジェクトを変更せずに射影することもできます。
次のセクションに、射影を実行する標準クエリ演算子メソッドの一覧を示します。
メソッド
メソッド名 |
Description |
C# のクエリ式の構文 |
Visual Basic のクエリ式の構文 |
詳細情報 |
---|---|---|---|---|
[Select] |
変換関数に基づく値を射影します。 |
select |
Select |
|
SelectMany |
変換関数に基づく値のシーケンスを射影し、それを 1 つのシーケンスに平坦化します。 |
複数の from 句を使用します。 |
複数の From 句を使用します。 |
クエリ式の構文の例
[Select]
次の例では、C# の select 句または Visual Basic の Select 句を使用して、文字列リストにある各文字列の最初の文字を射影します。
Dim words = New List(Of String) From {"an", "apple", "a", "day"}
Dim query = From word In words
Select word.Substring(0, 1)
Dim sb As New System.Text.StringBuilder()
For Each letter As String In query
sb.AppendLine(letter)
Next
' Display the output.
MsgBox(sb.ToString())
' This code produces the following output:
' a
' a
' a
' d
List<string> words = new List<string>() { "an", "apple", "a", "day" };
var query = from word in words
select word.Substring(0, 1);
foreach (string s in query)
Console.WriteLine(s);
/* This code produces the following output:
a
a
a
d
*/
SelectMany
次の例では、C# の from 句または Visual Basic の From 句を複数使用して、文字列リストにある各文字列の各単語を射影します。
Dim phrases = New List(Of String) From {"an apple a day", "the quick brown fox"}
Dim query = From phrase In phrases
From word In phrase.Split(" "c)
Select word
Dim sb As New System.Text.StringBuilder()
For Each str As String In query
sb.AppendLine(str)
Next
' Display the output.
MsgBox(sb.ToString())
' This code produces the following output:
' an
' apple
' a
' day
' the
' quick
' brown
' fox
List<string> phrases = new List<string>() { "an apple a day", "the quick brown fox" };
var query = from phrase in phrases
from word in phrase.Split(' ')
select word;
foreach (string s in query)
Console.WriteLine(s);
/* This code produces the following output:
an
apple
a
day
the
quick
brown
fox
*/
Select と SelectMany の比較
Select() と SelectMany() の機能はどちらも、ソース値から結果値 (複数も可) を生成することです。 Select() は、各ソース値ごとに結果値を 1 つ生成します。 したがって、結果全体は、ソース コレクションと同じ数の要素を持つコレクションになります。 一方、SelectMany() は、各ソース値から、連結されたサブ コレクションを含む 1 つの総合的な結果を生成します。 SelectMany() に引数として渡される変換関数は、各ソース値ごとに列挙可能な値のシーケンスを返す必要があります。 この列挙可能なシーケンスはその後 SelectMany() によって連結され、1 つの大きなシーケンスを作成します。
これら 2 つのメソッドのアクションの概念上の相違を次の 2 つの図に示します。 どちらの場合も、セレクター (変換) 関数が各ソース値から花の配列を選択すると仮定します。
ソース コレクションと同じ数の要素を持つコレクションを Select() が返すしくみを次の図に示します。
SelectMany() が中間配列シーケンスを、各中間配列の値を含む最終的な結果値に連結するしくみを次の図に示します。
コード例
次の例は、Select() と SelectMany() の動作を比較しています。 コードは、ソース コレクションの花の名前の各リストから最初の 2 つの項目を取って "花束" を作成します。 この例では、変換関数 Select``2(IEnumerableUMP, FuncUMP, UMP) が使用する "単一の値" 自体が値のコレクションになっています。 各サブ シーケンスで文字列を列挙するには追加の foreach (Visual Basic では For Each) ループが必要です。
Class Bouquet
Public Flowers As List(Of String)
End Class
Sub SelectVsSelectMany()
Dim bouquets = New List(Of Bouquet) From {
New Bouquet With {.Flowers = New List(Of String)(New String() {"sunflower", "daisy", "daffodil", "larkspur"})},
New Bouquet With {.Flowers = New List(Of String)(New String() {"tulip", "rose", "orchid"})},
New Bouquet With {.Flowers = New List(Of String)(New String() {"gladiolis", "lily", "snapdragon", "aster", "protea"})},
New Bouquet With {.Flowers = New List(Of String)(New String() {"larkspur", "lilac", "iris", "dahlia"})}}
Dim output As New System.Text.StringBuilder
' Select()
Dim query1 = bouquets.Select(Function(b) b.Flowers)
output.AppendLine("Using Select():")
For Each flowerList In query1
For Each str As String In flowerList
output.AppendLine(str)
Next
Next
' SelectMany()
Dim query2 = bouquets.SelectMany(Function(b) b.Flowers)
output.AppendLine(vbCrLf & "Using SelectMany():")
For Each str As String In query2
output.AppendLine(str)
Next
' Display the output
MsgBox(output.ToString())
' This code produces the following output:
'
' Using Select():
' sunflower
' daisy
' daffodil
' larkspur
' tulip
' rose
' orchid
' gladiolis
' lily
' snapdragon
' aster
' protea
' larkspur
' lilac
' iris
' dahlia
' Using SelectMany()
' sunflower
' daisy
' daffodil
' larkspur
' tulip
' rose
' orchid
' gladiolis
' lily
' snapdragon
' aster
' protea
' larkspur
' lilac
' iris
' dahlia
End Sub
class Bouquet
{
public List<string> Flowers { get; set; }
}
static void SelectVsSelectMany()
{
List<Bouquet> bouquets = new List<Bouquet>() {
new Bouquet { Flowers = new List<string> { "sunflower", "daisy", "daffodil", "larkspur" }},
new Bouquet{ Flowers = new List<string> { "tulip", "rose", "orchid" }},
new Bouquet{ Flowers = new List<string> { "gladiolis", "lily", "snapdragon", "aster", "protea" }},
new Bouquet{ Flowers = new List<string> { "larkspur", "lilac", "iris", "dahlia" }}
};
// *********** Select ***********
IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);
// ********* SelectMany *********
IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers);
Console.WriteLine("Results by using Select():");
// Note the extra foreach loop here.
foreach (IEnumerable<String> collection in query1)
foreach (string item in collection)
Console.WriteLine(item);
Console.WriteLine("\nResults by using SelectMany():");
foreach (string item in query2)
Console.WriteLine(item);
/* This code produces the following output:
Results by using Select():
sunflower
daisy
daffodil
larkspur
tulip
rose
orchid
gladiolis
lily
snapdragon
aster
protea
larkspur
lilac
iris
dahlia
Results by using SelectMany():
sunflower
daisy
daffodil
larkspur
tulip
rose
orchid
gladiolis
lily
snapdragon
aster
protea
larkspur
lilac
iris
dahlia
*/
}
参照
処理手順
方法 : LINQ の結合を使用してデータを結合する (Visual Basic)
方法: 複数のソースからオブジェクト コレクションにデータを設定する (LINQ)
方法 : LINQ クエリ結果を特定の型で返す (Visual Basic)
方法: グループを使用して 1 つのファイルを複数のファイルに分割する (LINQ)