LINQ
ハローワールド、プログラマのマツノブです。
社内製のツールを作っているとDBを使うほどじゃないけどデータ集計をしたいと思うことってありますよね?
そんなときは今回紹介するLINQがとても便利です。
LINQとは
統合言語クエリ (Language INtegrated Query; LINQ, リンクと発音する) とは、.NET Framework 3.5において、様々な種類のデータ集合に対して標準化された方法でデータを問い合わせること(クエリ)を可能にするために、言語に統合された機能のことである。開発ツールはVisual Studio 2008から対応している。
Wikiより
つまり、.NET Framework環境でDB的なクエリによるデータ集計ができる機能ということですね。
早速使っていきましょう。
今回はC#でのやり方を紹介していきます。
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="男性" },
};
上記のようなデータ配列があった場合で考えてみましょう。
// 男性のみ抽出
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風味のクエリ式による記述が可能です。
// 男性のみ抽出
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を高速に利用する
data.First(d => d.old);
と記述した場合
data.OrderBy(d => d.old).First();
と記述した場合と同じ結果を得ることができますが、
前述の場合先頭が確定した段階でソートが中止されるため後述より高速に処理することができます。
2次元配列を1次元配列にする
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を利用することが可能になります。
MatchCollection match;
match.Cast<Match>();
DataGridViewRowCollection row;
row.Cast<DataGridViewRow>();