2015年12月1日火曜日

.Net(VB C#) LINQ
Enumerable.Select メソッド

Enumerable.Select メソッド
【C#】
シーケンスの各要素を新しいフォームに射影します。
public static IEnumerable<TResult> Select<TSource, TResult>
    (this IEnumerable<TSource> source, Func<TSource, TResult> selector)

要素のインデックスを組み込むことにより、シーケンスの各要素を新しいフォームに射影します。
public static IEnumerable<TResult> Select<TSource, TResult>
    (this IEnumerable source, Func selector)
【VB】
シーケンスの各要素を新しいフォームに射影します。
<ExtensionAttribute>
Public Shared Function Select(Of TSource, TResult) 
    (source As IEnumerable(Of TSource), selector As Func(Of TSource, TResult)) 
    As IEnumerable(Of TResult)

要素のインデックスを組み込むことにより、シーケンスの各要素を新しいフォームに射影します。
<ExtensionAttribute>
Public Shared Function Select(Of TSource, TResult) 
    (source As IEnumerable(Of TSource), selector As Func(Of TSource, Integer, TResult)) 
    As IEnumerable(Of TResult)

簡単に言うと…
シーケンス(配列やコレクションなど)の要素から特定のプロパティを取り出し、新しい要素のシーケンスを作成する。

このメソッドは遅延実行されます。


テストデータです。
【C#】
private class Fruit
{
    public string Name { get; set; }
    public string Rank { get; set; }
    public decimal Price { get; set; }
}

var fruits = new List<Fruit>()
                {
                    new Fruit(){Name = "りんご", Rank = "A" , Price = 1000 },
                    new Fruit(){Name = "みかん", Rank = "A" , Price = 600 },
                    new Fruit(){Name = "ぶどう", Rank = "B" , Price = 1200 },
                    new Fruit(){Name = "りんご", Rank = "B" , Price = 800 },
                    new Fruit(){Name = "みかん", Rank = "A" , Price = 500 }
                };
【VB】
Private Class Fruit
    Public Property Name As String
    Public Property Rank As String
    Public Property Price As Decimal
End Class

Dim fruits = New List(Of Fruit)() From
            {
                New Fruit() With {.Name = "りんご", .Rank = "A", .Price = 1000},
                New Fruit() With {.Name = "みかん", .Rank = "A", .Price = 600},
                New Fruit() With {.Name = "ぶどう", .Rank = "B", .Price = 1200},
                New Fruit() With {.Name = "りんご", .Rank = "B", .Price = 800},
                New Fruit() With {.Name = "みかん", .Rank = "A", .Price = 500}
            }


まず果物リストの各果物要素の名前だけを取り出します。
【C#】
var nameList = fruits.Select(itm => itm.Name);

//出力
foreach (var itm in nameList)
    Console.WriteLine("名称={0}", itm);  
//名称=りんご
//名称=みかん
//名称=ぶどう
//名称=りんご
//名称=みかん 
【VB】
Dim nameList = fruits.Select(Function(itm) itm.Name)

'出力
For Each itm In nameList
    Console.WriteLine("名称={0}", itm)
Next
'名称=りんご
'名称=みかん
'名称=ぶどう
'名称=りんご
'名称=みかん

次に名前と値段(税込)を取り出してみます。
複数のプロパティを取り出す場合、匿名クラスを利用します。
※匿名クラスでなく、普通のクラスも利用できます。
【C#】
var lst = fruits.Select(itm => new { itm.Name, ZeikomiPrice = itm.Price * 1.08m });

//出力
foreach (var itm in lst)
    Console.WriteLine("名称={0}, 値段(税込)={1}", itm.Name, itm.ZeikomiPrice.ToString("#,##0"));  
//名称=りんご, 値段(税込)=1,080
//名称=みかん, 値段(税込)=648
//名称=ぶどう, 値段(税込)=1,296
//名称=りんご, 値段(税込)=864
//名称=みかん, 値段(税込)=540  
【VB】
Dim lst = fruits.Select(Function(itm) New With {itm.Name, .ZeikomiPrice = itm.Price * 1.08D})

'出力
For Each itm In lst
    Console.WriteLine("名称={0}, 値段(税込)={1}", itm.Name, itm.ZeikomiPrice.ToString("#,##0"))
Next
'名称=りんご, 値段(税込)=1,080
'名称=みかん, 値段(税込)=648
'名称=ぶどう, 値段(税込)=1,296
'名称=りんご, 値段(税込)=864
'名称=みかん, 値段(税込)=540   

匿名クラスを利用せずに、普通のクラスを利用して、値段を2倍した果物リストを作成します。
【C#】
var lst = fruits.Select(itm => new Fruit(){Name = "ボッタクリ" + itm.Name, Rank = itm.Rank, Price = itm.Price * 2});

//出力
foreach (var itm in lst)
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));
//名称=ボッタクリりんご, ランク=A, 値段=2,000
//名称=ボッタクリみかん, ランク=A, 値段=1,200
//名称=ボッタクリぶどう, ランク=B, 値段=2,400
//名称=ボッタクリりんご, ランク=B, 値段=1,600
//名称=ボッタクリみかん, ランク=A, 値段=1,000 
【VB】
Dim lst = fruits.Select(Function(itm) _
   New Fruit() With {.Name = "ボッタクリ" + itm.Name, .Rank = itm.Rank, .Price = itm.Price * 2})

'出力
For Each itm In lst
 Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"))
Next
'名称=ボッタクリりんご, ランク=A, 値段=2,000
'名称=ボッタクリみかん, ランク=A, 値段=1,200
'名称=ボッタクリぶどう, ランク=B, 値段=2,400
'名称=ボッタクリりんご, ランク=B, 値段=1,600
'名称=ボッタクリみかん, ランク=A, 値段=1,000 

Selectメソッドは各要素のインデックスが取得できるオーバーロードがあります。
各要素のインデックスが取得できるSelectメソッドを使用して、果物リストからインデックスを取り出します。
【C#】
var lst = fruits.Select((itm, idx) => new { Index = idx, Name = itm.Name});

//出力
foreach (var itm in lst)
    Console.WriteLine("インデックス={0}, 名称={1}", itm.Index, itm.Name);
//インデックス=0, 名称=りんご
//インデックス=1, 名称=みかん
//インデックス=2, 名称=ぶどう
//インデックス=3, 名称=りんご
//インデックス=4, 名称=みかん
【VB】
Dim lst = fruits.Select(Function(itm, idx) New With {.Index = idx, itm.Name})

'出力
For Each itm In lst
    Console.WriteLine("インデックス={0}, 名称={1}", itm.Index, itm.Name)
Next
'インデックス=0, 名称=りんご
'インデックス=1, 名称=みかん
'インデックス=2, 名称=ぶどう
'インデックス=3, 名称=りんご
'インデックス=4, 名称=みかん
※VBの場合、コンパイルオプションで「Option Infer」をONにし、型推論を有効にしてください。

.Net(VB C#) LINQのメソッド一覧

0 件のコメント: