C#のLINQを使ってみる

今回はC#でLINQを使ってみます。

通常であれば、SQLデータベース、XMLドキュメントといった様々な種類のデータ毎にクエリ(データにアクセス、操作する手段)演算が必要ですが、

LINQを使うとそれを同じようなクエリ演算を使ってする事が出来ます。

LINQについてはC#リファレンスを参考にしました。

C# における統合言語クエリ (LINQ) の概要

クエリを使う事が出来るのは、IEnumarable<T>かIQueryable<T> というインタフェースを実装しているクラスになります。

ListはIEnumerableを継承しているので使用する事が出来ますね。

スポンサーリンク

LINQを使う

LINQを使うには

usingディレクティブでSystem.Linqを指定します。

これでMonoDevelopのインテリセンス機能?でLINQのメソッドが現れるようになります。

実際にいくつかのLINQのメソッドを実行して確認してみます。

操作をする配列、List、Dictionaryのデータを用意し、これらの要素を操作してみます。

それぞれ初期値を与えています。

条件が成立しているか判断するメソッド

Anyメソッド

Anyメソッドは条件に合う要素があるかどうかでbool値を返します。
ひとつでもあればtrueを返します。

↑の場合はstringValueにはtest1、test2という要素があるのでtrueが返ります。

Allメソッド

Allメソッドは全ての要素が条件を満たしているかどうかを返します。

↑の例ではtrueが表示されます。

条件にあった要素を抽出しIEnumerableインタフェースを返すメソッド

Whereメソッド

Whereメソッドは条件に合う要素からIEnumerableのジェネリックを返します。

↑の例ではlistから5以上の要素でIEnumerableのジェネリックを返すので、foreach文等で要素を表示すると 5 6 7 8 9 9 8 7 6 5 が表示されます。

Whereメソッドは遅延実行なので、tempList2を使用する時にlist.Where(x => x >= 5)が実行されtempList2が決まる事になります。

遅延実行については後ほどやります。

Distinctメソッド

Distinctメソッドは要素の中から重複する値を持つ要素を削除してIEnumerableのインタフェースを返します。

foreach文等を使ってenumerableListを表示すると、1 2 3 4 5 6 7 8 9 という要素が表示されます。

Takeメソッド

Takeメソッドは要素の中から指定した数の要素を取得しIEnumerableジェネリックインタフェースを返します。

foreach文などでtempList3の要素を表示すると 1 2 が表示されます。

TakeWhileメソッド

TakeWhileメソッドを使用すると、要素が条件に合っている間要素を取得し、IEnumerableジェネリックインタフェースを返します。

↑の例では要素が4以下の間要素を取りだしているので要素の値が5になった時点で終了します。

foreachでtempList4の要素を出力すると 1 2 3 4 が表示されます。

OrderByメソッド

OrderByメソッドを使うと要素を昇順に並べ替えをする事が出来ます。

↑の例ではlistの要素を昇順に並べ替えています。

OrderByDescendingメソッド

OrderByDescedingメソッドを使用すると要素を降順に並べ替える事が出来ます。

OrderBy、OrderByDecendingで比較方法を指定

OrderByやOrderByDecendingの引数にICompareインタフェースを実装したクラスを渡すと、比較方法を変更する事が出来ます。

まずはICompareクラスを実装したクラスを作成し、比較メソッドであるCompareを作成します。

↑の例ではyからxを引くようにしているので要素の数を降順に並べ替えます。

実際に使う場合は

listの要素の値をCompareClassのCompareで指定されている並びに変更しています。

listの要素が文字列で、文字列の長さで並べ替えをしたい時は

要素を使った操作メソッド

Average

Averageメソッドは要素の平均値を求める事が出来ます。

listリストの要素の平均値は5が表示されます。

Countメソッド

CountメソッドはListクラスのメソッドもあり要素数を返す事が出来ますが、LINQのCountメソッドを使うとPredicateデリゲートやラムダ式で条件にあった要素の数を返す事が出来ます。

↑の例ではlistの要素で7以上の数値の要素を返すので6が表示されます。

条件に合う要素を抽出

Firstメソッド

Firstメソッドは要素の中から条件にあった最初の要素を取得しますが、要素がなかった場合は例外が発生します。

↑の例では1が表示されます。

FirstOrDefaultメソッド

FirstOrDefaultメソッドは要素の中から条件にあった最初の要素を取得しますが、要素がなかった場合はその要素の型のデフォルト値が返ってきます。

↑の例では要素の中に10以上の値はないので、要素のint型のデフォルト値である0が返ってきます。

即時実行と遅延実行

WhereメソッドやDistinctメソッドではIEnumerableのジェネリックを値として取得出来ますが、Distinctの実行はその値を使う時にあらためてlistを取得し実行する遅延実行です。

その為Distinctメソッドの項目で作成したenumerableListを使った処理をする時に、list.Distinctが実行されenumerableListの値を作成します。

なので、enumerableListを作成した後に元のリストを変更した場合、その後のenumerableListも変更されます。

試しに以下のようなスクリプトを記述してみます。

↑の例ではlistから重複する要素を取り除いた 1 2 3 4 5 6 7 8 9 という要素を持つenumerableListを作成します。

その後listから3以上の要素を削除します。

最後にenumerableListの要素を出力しますが、表示されるのは 1 2 となります。

単純に考えたらlistの中身を変更する前にenumerableListを作っているので 1 2 3 4 5 6 7 8 9 と表示されそうですが、Distinctは遅延実行なので、enumerableListを使う時にlist.Distinctを実行し、それがenumerableListに入ります。

遅延実行をしたくない時は、ToArray、ToList、ToDictionary等を使ってその場で配列やリスト、ディクショナリに変更します。

WhereやDistinct以外のメソッドでも遅延実行をするものがあるので、使う時に気を付けないといけません。

ToDictionaryでDictionaryを作成してみます。

↑の例ではdictionaryのキーと値のペアがdicに渡され、そのキーにkeyという文字が含まれているものを抽出し、それをToDictionaryでDictionaryに変換しています。

ToDictionaryではキーと値をどれにするかを設定します。

結果は key1 0、 key2 1、 key3 2 が表示されます(otherにはkeyという文字列が含まれない為登録されません)。

チェーンメソッド

LINQはIEnumerableに対して行えるので、Whereメソッドの後にTake、ToList等、メソッドを繋げて実行する事も可能です。

↑の例ではWhereの戻り値であるIEnumerableに対してTake(5)を実行し、IEnumerableが返ってきて、さらにそれに対してToListを実行しリスト化しています。

結果として 2 3 4 5 6 が表示されます。

全サンプル

最後に全てのサンプルを搭載したスクリプトを掲載します。

実行結果は各自確認してみてください。(^_^;)

終わりに

LINQのメソッドは他にもありますが、ざっくりと紹介しました。

後で追記するかもしれません。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます