C#の配列から条件に合う要素を抽出する(LINQ Where)

C#
C#には LINQ というライブラリがあります。
LINQ を使えばコレクション(配列や List クラスなど)に対する処理を簡単に行う事が出来ます。

ここでは、LINQ を使って配列に格納された要素の中から条件を満たすものを抜き出す方法について解説します。


LINQとは

LINQ は IEnumerable<T>インターフェースへの拡張メソッドとして作られています。
つまり、配列Listクラス、Dictionaryクラス、ObservableCollectionクラスなどのIEnumerable<T>インターフェースを実装するオブジェクトであればどれでも同じように使用する事ができます。

LINQをつかうには using で System.Linq を参照できるようにしておきましょう。

using System.Linq;



条件に合う要素を抽出する Where メソッド

条件に合う要素を抽出するには Where メソッドを使用します。
引数に条件式を指定しますが、ラムダ式を使って記述するのが簡単で一般的な方法です。

※ラムダ式の詳細は「C#のラムダ式【=>】って何?」をご覧ください


抽出した要素だけに処理する例

以下の例では文字列が入った配列の中から「i」が使われている要素だけを抽出しています。

            string[] testArray = new string[5];
            testArray[0] = "Taro";
            testArray[1] = "Jiro";
            testArray[2] = "Saburo";
            testArray[3] = "Shiro";
            testArray[4] = "Goro";
 
            IEnumerable<string> testWhere = testArray.Where(o => o.IndexOf('i') >= 0);
 
            foreach (string item in testWhere)
            {
                Console.WriteLine(item);
            }

Whereメソッドの戻り値はIEnumerable<T>です。
※元の配列の要素がstring型なのでIEnumerable<string>になります

IEnumerable<T>はそのまま foreach 文で利用する事が出来ます。


抽出した要素を別の配列にする例

LINQ には 結果を配列として取得する ToArray() や、 Listクラスとして取得する ToList() メソッドがあります。

            IEnumerable<string> testWhere = testArray.Where(o => o.IndexOf('i') >= 0);
            string[]            testArray2 = testWhere.ToArray();

以下のように1行で書くことも出来ます。

            string[] testArray2 = testArray.Where(o => o.IndexOf('i') >= 0).ToArray();



複数の値の中からどれかと一致する要素を抽出する例

SQL文ではいずれかに一致するものを抽出するという時の為に「IN」という演算子があります。
「WHERE [ID] IN (2,3,5,8)」みたいな書き方が出来ます。

同じような事をLINQで行うには Contains メソッドを合わせて使うと良さそうです。

            string[] testArray = new string[5];
            testArray[0] = "Taro";
            testArray[1] = "Jiro";
            testArray[2] = "Saburo";
            testArray[3] = "Shiro";
            testArray[4] = "Goro";
 
            string[] conditions = new string[2];
            conditions[0] = "Jiro";
            conditions[1] = "Saburo";
 
            IEnumerable<string> testWhere = testArray.Where(o => conditions.Contains(o));
 
            foreach (string item in testWhere)
            {
                Console.WriteLine(item);
            }


LINQは遅延実行される

上記のToArray()で配列を取得している例をみると、
  1. Whereメソッドで IEnumerable<T>にデータが作られる
  2. ToArrayメソッドで配列の形式にデータが変換される
のように見えて二度手間な感じがしてしまいますが、実際の動きは少し異なります。

戻り値が IEnumerable<T> となるメソッドでは、データに対するアクションは行われません。
Whereメソッドはどのような処理をするかというコマンドだけを溜め込んでいるような状態です。

LINQ は foreach 文や ToArrayなどのメソッドを実行する時にデータが作成されます。
このような仕組みによって、複数回Whereを使ったり他のLINQメソッドと併用しても高速に結果を得られるようになっています。





コメント