クエリ式というのを書いてみた。
語句
- from
- select
- where
- orderby
- group
- into
- let
- join
- join into
語句
次に記述する語句は以下のデータを操作してるものとして記述している。
var persons = new []{ new {name = "a", Job = Job.archer, HP = 1, Luck = 1.3, like = "cherry" }, new {name = "a", Job = Job.magician, HP = 2, Luck = 1.2, like = "banana" }, new {name = "b", Job = Job.knight, HP = 3, Luck = 1.1, like = "lemon" }, new {name = "b", Job = Job.axman, HP = 1, Luck = 1.3, like = "peach" }, new {name = "c", Job = Job.magician, HP = 2, Luck = 1.2, like = "orange" }, new {name = "c", Job = Job.witch, HP = 3, Luck = 1.1, like = "orange" }, new {name = "a", Job = Job.witch, HP = 2, Luck = 1.6, like = "apple" }, new {name = "e", Job = Job.magician, HP = 5, Luck = 1.1, like = "lemon" }, new {name = "d", Job = Job.archer, HP = 8, Luck = 1.3, like = "pine" }, };
Jobはenumで定義してるものとする。
public enum Job{ knight,magician,axman,archer,witch,swordman }
from
var data = from p in persons select p;
foreachの中に書く文を続ける様に、from の後に語句を連結することで、さらにフィルタリングしたり並べ替えたりできる。
定型句として先に記述するものとして理解。
select
var data = from p in persons select p;
抽出、並べ替え等のあとに最後に返す内容。
select p * p;
と書くと乗算したデータの羅列になる。
orderby
並べ替え用の語句。
var data = from p in persons orderby p.HP descending, p.Job select p;
HPで降順に並び替えをし、同数だった場合はJobで順位付けを行う、という内容。
where
フィルタリング。条件を記述することで以降の語句で記述する文の処理の対象から外す。
var groupByHP = from x in persons where x.Key >= 3 select grouped;
group
グループ化する語句。
var groupByHP = from x in persons group x by x.HP
これは、同じHPどうしで全員をグルーピングしたということ。
var groupByHP = from x in persons group x by x.HP into grouped where grouped.Key >= 3 // filter select grouped;
条件にあったグループだけ抽出したい場合はこう書く。
グループ条件はKeyに格納されるのでKeyが3以上、つまりHPが3以上になったグループだけを抽出したということ。
グループ化したオブジェクトは以下の様に取得できる。
foreach (var a in groupByHP) { Console.WriteLine ("HP:"+a.Key +" persons are.."); foreach (var b in a) { Console.WriteLine ("t"+b); } } /* HP:1 persons are.. { name = a, Job = archer, HP = 1, Luck = 1.3, like = cherry } { name = b, Job = axman, HP = 1, Luck = 1.3, like = peach } HP:2 persons are.. { name = a, Job = magician, HP = 2, Luck = 1.2, like = banana } { name = c, Job = magician, HP = 2, Luck = 1.2, like = orange } { name = a, Job = witch, HP = 2, Luck = 1.6, like = apple } HP:3 persons are.. { name = b, Job = knight, HP = 3, Luck = 1.1, like = lemon } { name = c, Job = witch, HP = 3, Luck = 1.1, like = orange } HP:5 persons are.. { name = e, Job = magician, HP = 5, Luck = 1.1, like = lemon } HP:8 persons are.. { name = d, Job = archer, HP = 8, Luck = 1.3, like = pine } */
into
直前までの条件であらたな識別子を持ったオブジェクトの集合を作成するための語句。
var groupByHP = from x in persons group x by x.HP into grouped where grouped.Key >= 3 // filter select grouped;
let
途中出力した内容を保持するための語句。
letで宣言するような使い方。
ここでデータを追加しておく。
var items = new []{ new {name = "banana", heal = 20}, new {name = "apple", heal = 32}, new {name = "cherry", heal = 53}, new {name = "peach", heal = 25}, new {name = "pine", heal = 89}, new {name = "orange", heal = 57}, new {name = "lemon", heal = 11}, };
letを使用した例はこちら。
Console.WriteLine ("nlist up liked == item.name:where"); var likePattern = from man in persons from item in items where man.like == item.name let newName = man.name +"(" + man.Job.ToString() +")" + " with " + item.name let newHP = man.HP + item.heal * man.Luck select new {name = newName,HealedHP = newHP} ;
join
新たなオブジェクトを作成する。
join … on .. equals でセット。
例は、データを次のルールで加工する。
好きな果物を食べるとLuck係数分多く回復する。
where を使って上記のルールを達成した文。
var likePattern = from man in persons from item in items where man.like == item.name let newName = man.name +"(" + man.Job.ToString() +")" + " with " + item.name let newHP = man.HP + item.heal * man.Luck select new {name = newName,HealedHP = newHP} ;
結果
{ name = a(archer) with cherry, HealedHP = 69.9 } { name = a(magician) with banana, HealedHP = 26 } { name = b(knight) with lemon, HealedHP = 15.1 } { name = b(axman) with peach, HealedHP = 33.5 } { name = c(magician) with orange, HealedHP = 70.4 } { name = c(witch) with orange, HealedHP = 65.7 } { name = a(witch) with apple, HealedHP = 53.2 } { name = e(magician) with lemon, HealedHP = 17.1 } { name = d(archer) with pine, HealedHP = 123.7 }
これを join で書くと以下の様になる。
var writeByJoin = from man in persons join item in items on man.like equals item.name let newName = man.name +"(" + man.Job.ToString() +")" + " with " + item.name let newHP = man.HP + item.heal * man.Luck select new {name = newName,HealedHP = newHP} ;
出力される内容は全く同じ。
join into
入れ子になったオブジェクトを作成する。
into は先の説明でもあったとおり、新たに識別子をもったオブジェクトを作成する。
var fruiteLike = from item in items join man in persons on item.name equals man.like into ps select new {name = item.name,persons = ps.Select( y => y.name + "(" + y.Job.ToString() + ")" )} ;
ソース
実際に書いてみた内容はこちら。->gist