2015年12月11日金曜日

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

Enumerable.TakeWhileメソッド
【C#】
指定された条件を満たされる限り、シーケンスから要素を返した後、残りの要素をスキップします。
public static IEnumerable<TSource> TakeWhile<TSource>
    (this IEnumerable<TSource> source, Func<TSource, bool> predicate)

指定された条件が満たされる限り、シーケンスから要素を返します。要素のインデックスは、述語関数のロジックで使用されます。
public static IEnumerable TakeWhile
    (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
【VB】
指定された条件を満たされる限り、シーケンスから要素を返した後、残りの要素をスキップします。
<ExtensionAttribute>
Public Shared Function TakeWhile(Of TSource) 
    (source As IEnumerable(Of TSource), predicate As Func(Of TSource, Boolean))
     
指定された条件が満たされる限り、シーケンスから要素を返します。要素のインデックスは、述語関数のロジックで使用されます。
<ExtensionAttribute>
Public Shared Function TakeWhile(Of TSource) 
    (source As IEnumerable(Of TSource), predicate As Func(Of TSource, Integer, Boolean)) 
    As IEnumerable(Of TSource)


簡単に言うと…
シーケンス(配列やコレクション)の先頭から、指定された条件に該当する間その要素を返します。

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


テストデータです。
【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}
            }
TakeWhileメソッドを使用して、先頭から値段が1000円以下の条件が満たされる間、その要素を取得します。
つまり、先頭から順に1000円以下かどうか判定し、1000円以下であればその要素を返します。
ぶどうが1200円ですので条件には該当しません。ここで判定はストップします。
ぶどう以降のりんごやみかんは1000円以下ですが無視されます。

【C#】
//先頭から値段が1000円以下の条件が満たされる間、その要素を取得します。
var lst1 = fruits.TakeWhile(itm => itm.Price <= 1000);
//出力
foreach (var itm in lst1)
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));  
//名称=りんご, ランク=A, 値段=1,000
//名称=みかん, ランク=A, 値段=600
【VB】
'先頭から値段が1000円以下の条件が満たされる間、その要素を取得します。
Dim lst1 = fruits.TakeWhile(Function(itm) itm.Price <= 1000)
'出力
For Each itm In lst1
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"))
Next
'名称=りんご, ランク=A, 値段=1,000
'名称=みかん, ランク=A, 値段=600
各要素のインデックスを取得できるオーバーロードメソッドもあります。
以下のコードではインデックスが3以下の間、その要素を取得します。
※Takeメソッドは引数に取得する個数を指定します。Take(3)と指定すると先頭から3つの要素を取得します。
【C#】
//インデックスが3以下の条件が満たされる間、その要素を取得します。
var lst1 = fruits.TakeWhile((itm, idx) => idx <= 3);
//出力
foreach (var itm in lst1)
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));  
//名称=りんご, ランク=A, 値段=1,000
//名称=みかん, ランク=A, 値段=600
//名称=ぶどう, ランク=B, 値段=1,200
//名称=りんご, ランク=B, 値段=800
【VB】
'インデックスが3以下の条件が満たされる間、その要素を取得します。
Dim lst1 = fruits.TakeWhile(Function(itm, idx) idx <= 3)
'出力
For Each itm In lst1
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"))
Next
'名称=りんご, ランク=A, 値段=1,000
'名称=みかん, ランク=A, 値段=600
'名称=ぶどう, ランク=B, 値段=1,200
'名称=りんご, ランク=B, 値段=800    

※VBの場合、コンパイルオプションで「Option Infer」をONにし、型推論を有効にしてください。

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

0 件のコメント: