ハローワールド、プログラマのマツノブです。
社内製のツールを作っているとDBを使うほどじゃないけどデータ集計をしたいと思うことってありますよね?
そんなときは今回紹介するLINQがとても便利です。
LINQとは
統合言語クエリ (Language INtegrated Query; LINQ, リンクと発音する) とは、.NET Framework 3.5において、様々な種類のデータ集合に対して標準化された方法でデータを問い合わせること(クエリ)を可能にするために、言語に統合された機能のことである。開発ツールはVisual Studio 2008から対応している。
https://ja.wikipedia.org/wiki/統合言語クエリ
Wikiより
つまり、.NET Framework環境でDB的なクエリによるデータ集計ができる機能ということですね。
早速使っていきましょう。
今回はC#でのやり方を紹介していきます。
1 2 3 4 5 6 7 8 9 |
var data = new [] { new { name="一郎", old=32, job="プログラマ", sexuality="男性" }, new { name="花子", old=25, job="デザイナー", sexuality="女性" }, new { name="正子", old=28, job="事務員", sexuality="女性" }, new { name="太郎", old=24, job="プランナー", sexuality="男性" }, new { name="次郎", old=29, job="プログラマ", sexuality="男性" }, new { name="三郎", old=35, job="デザイナー", sexuality="男性" }, }; |
上記のようなデータ配列があった場合で考えてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 男性のみ抽出 var mens = data.Where(d => d.sexuality == "男性"); foreach (var man in mens) { Console.WriteLine(man.name); } // 年齢の最も高い人を抽出 var older = data.OrderByDescending(d => d.old).First(); Console.WriteLine(older.name); // 平均年齢を計算 var ave = data.Average(d => d.old); Console.WriteLine(ave.ToString()); |
LINQのメソッドは配列やLIST型の拡張メソッドとして実装されています。
今回使用した各メソッドは
- Where
条件にマッチしたものを抽出する。 - OderBy/OrderByDescending
昇順/降順でソートする。 - First
リストの先頭を取得する。 - Average
値の平均を取得する。
となっています。
上記のような拡張メソッドの他にもSQL風味のクエリ式による記述が可能です。
1 2 3 4 5 6 7 8 9 10 |
// 男性のみ抽出 var mens = from x in data where x.sexuality == "男性" select x; foreach (var man in mens) { Console.WriteLine(man.name); } // 年齢の最も高い人を抽出 var older = (from x in data orderby x.old descending select x).First(); Console.WriteLine(older.name); |
AverageやFirstといった一部のメソッドにはクエリ式がないものもあります。
前述したとおりLINQは.NET Frameworkの機能なのでDBやSQLiteのような環境構築なしに利用することができます。
みなさんもDBを使うほどではないデータ集計に利用してみてください。
最後にLINQを使う上で役立つTIPSを紹介して今回は終わりです。
OderBy+Firstを高速に利用する
1 |
data.First(d => d.old); |
と記述した場合
1 |
data.OrderBy(d => d.old).First(); |
と記述した場合と同じ結果を得ることができますが、
前述の場合先頭が確定した段階でソートが中止されるため後述より高速に処理することができます。
2次元配列を1次元配列にする
1 2 3 4 5 6 7 8 9 |
int[][] int_array = new int[][] { new int[]{ 10, 100, 50, 25, 30 }, new int[]{ 20, 200, 60, 28, 34 }, new int[]{ 18, 150, 58, 75, 8 }, new int[]{ 9, 108, 48, 35, 20 }, }; int[] a = int_array.SelectMany(x => x).ToArray(); |
XXX_Collection 型でLINQを使用する
MatchCollection や DataGridViewRowCollection にはLINQの拡張メソッドが用意されていないためそのままではLINQを利用することができません。
ですが Cast メソッドを使うことで配列に変換しLINQを利用することが可能になります。
1 2 3 4 5 |
MatchCollection match; match.Cast<Match>(); DataGridViewRowCollection row; row.Cast<DataGridViewRow>(); |