2015年12月2日水曜日

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

Enumerable.Where メソッド
【C#】
述語に基づいて値のシーケンスをフィルター処理します。
public static IEnumerable<TSource> Where<TSource>
    (this IEnumerable<TSource> source, Func<TSource, bool> predicate)

述語に基づいて値のシーケンスをフィルター処理します。各要素のインデックスは、述語関数のロジックで使用されます。
public static IEnumerable<TSource> Where<TSource>
    (this IEnumerable source, Func predicate)
【VB】
述語に基づいて値のシーケンスをフィルター処理します。
<ExtensionAttribute>
Public Shared Function Where(Of TSource) 
    (source As IEnumerable(Of TSource), predicate As Func(Of TSource, Boolean)) 
    As IEnumerable(Of TSource)

述語に基づいて値のシーケンスをフィルター処理します。各要素のインデックスは、述語関数のロジックで使用されます。
<ExtensionAttribute>
Public Shared Function Where(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}
            }
果物リストから「ランクがAか値段が1000円以上」の果物を抽出します。

【C#】
var expensiveList = fruits.Where(itm => itm.Rank == "A" || itm.Price >= 1000);
            
//出力
foreach (var itm in expensiveList)
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));
//名称=りんご, ランク=A, 値段=1,000
//名称=みかん, ランク=A, 値段=600
//名称=ぶどう, ランク=B, 値段=1,200
//名称=みかん, ランク=A, 値段=500
【VB】
 Dim expensiveList = fruits.Where(Function(itm) itm.Rank = "A" OrElse itm.Price >= 1000)

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

各要素のインデックスが取得できるWhereメソッドを使用して、
果物リストから偶数のインデックスの要素を抽出します。

【C#】
var evenList = fruits.Where((itm, idx) => (idx % 2) == 0);

//出力
foreach (var itm in evenList)
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"));
//名称=りんご, ランク=A, 値段=1,000
//名称=ぶどう, ランク=B, 値段=1,200
//名称=みかん, ランク=A, 値段=500 
【VB】
Dim evenList = fruits.Where(Function(itm, idx) idx Mod 2 = 0)

'出力
For Each itm In evenList
    Console.WriteLine("名称={0}, ランク={1}, 値段={2}", itm.Name, itm.Rank, itm.Price.ToString("#,##0"))
Next
'名称=りんご, ランク=A, 値段=1,000
'名称=ぶどう, ランク=B, 値段=1,200
'名称=みかん, ランク=A, 値段=500
※VBの場合、コンパイルオプションで「Option Infer」をONにし、型推論を有効にしてください。

画面の検索条件などによりWhereメソッドの条件を動的に組み立てる事があると思います。
And検索であれば特に問題ないと思いますが、OR検索はWhereメソッドを単純に使用するだけでは実現できません。
いろいろ方法はあると思いますが、Whereメソッドを使用した簡単なOr検索を実現する方法をコチラに書いてみました。
.Net(VB C#) LINQ Enumerable.Where メソッドのAND条件やOR条件を動的に組み立てる

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

0 件のコメント: