概要
ちらっと見たら Where
だの Skip
だのあったから、 Python の高階関数とか内包表記のことか? と思ったけどもっと広範囲な、シーケンス(リストとかそういうの)全体をスマートに操作する話っぽい。
流し読みノート
LINQ って?
- 情報セットを扱うツール郡。
- LINQ プロバイダっていって、いくつかある。フツーは LINQ to Objects ってやつでいい。まあフツーっぽいよね。
LINQ プロバイダの種類
- LINQ to Entities: Entity Framework っていう…… Python の Django にもある ORM モデルの DB 操作ツール? の一部なんだって。
- これを使うときはラムダ必須で、匿名メソッド、デリゲートは不可らしい。デリゲを使うと、 DB の情報をすべてダウンロードしたあとクライアント側で絞り込むみたいなことが起こる模様。
- こないだやったことがそのまま出てきたね! 匿名メソッドは
delegate
で定義されたインラインメソッドのこと(delegate (int value) { return value > 0; }
)。そしてラムダはこれ。(int value) => { return value > 0; }
- こないだやったことがそのまま出てきたね! 匿名メソッドは
- これを使うときはラムダ必須で、匿名メソッド、デリゲートは不可らしい。デリゲを使うと、 DB の情報をすべてダウンロードしたあとクライアント側で絞り込むみたいなことが起こる模様。
- LINQ to SQL: SQLServer っていう DB 専用のやつ。
- LINQ to XML: これは LINQ プロバイダじゃねえ。罠だ。 XML 用の API らしい。
DB とか XML にそれぞれ適したツールセットがあるわけなんだ。 LINQ to Objects はフツーの C# のシーケンスに使えるんだろう。そりゃあ、とりあえずこれを覚えておきたいところだ。
LINQ の例
国や地域の情報が詰まっている CultureInfo
っていうオブジェクトがあるから、それをぐるぐる回して、「小数区切りにピリオドじゃなくてカンマを使っている」 culture を探し出してみようや。てかまずそんな国があることにビックリだがな。
using System.Globalization;
// ↓LINQ の返り値はこの型になるっぽい? Python のイテレータみたいなもんかな?
IEnumerable<string> commaCultures =
// ↓おお! Python の for in やんけ! しかも…… from のほうが初心者のころ意味が取りやすいか……?!
from culture in CultureInfo.GetCultures(CultureTypes.AllCultures)
// ↓小数点が , のやつをとる。なんだとぉ…… Python の filter() や内包表記より見やすいんじゃねーか……?
where culture.NumberFormat.NumberDecimalSeparator == ","
// ↓しかも連結の途中で変数定義もできる?!
let name = culture.Name
// ↓そして最後に、欲しいものを取り出す、と……。
select name;
foreach (string _ in commaCultures)
{
// 取得したものを print してみる。 af af-NA af-ZA agq agq-CM ar-MR ... って出てくる。どこやこれ。
Console.WriteLine(_);
}
えっ? スゴ……。(トゥンク ダメよあたしには Python がいるのに……。ちなみにだな、 Python で同じようなことを内包表記でやるとこうなるぞ……。 CultureInfo
にあたるものは思い至らないんで、3の倍数を取り出す内包表記を書いてみよう。
result = (
# select に当たるものはこれ。昔から思ってはいたけど、最終的に欲しいものが最初にあるのはわかりづらい……。
i
# from in に当たるものはこれ。まあこれは同点か。
for i in range(100)
# 途中で変数定義なんてもちろん無い。
# where に当たるものはこれ。まあこれも同点かね。
if i % 3 == 0
)
for r in result:
print(r)
うーーーん、これは Pythonista でも C# に軍配を上げる!! いや待て、確かに途中で変数定義できるのはステキだが、 Python はひとつの文を長くするのを防ぐためにそれを禁じているという見方もできる! 確かに途中で変数定義できるのはステキだがな! でも文の順序については文句なしで LINQ がスゴイわ!
LINQ 演算子という用語
- LINQ 演算子っていうのは
+
とか&&
のことではない。 LINQ プロバイダのクエリ機能のことだ。Where
とか。 - 突然出てきた
Where
だけど、↑で感動したwhere
とは違う。Where
はメソッドチェーンで LINQ を書くとき使うもの……演算子……で、where
はクエリ式で書くときのもの。- クエリ式がさっぱりしてるから使いたいけど、結局コンパイラがメソッドチェーンに変換するらしいよ。
- 演算子はたくさんある。
演算子 | 用途 |
---|---|
Aggregate | 指定した関数で全項目を結合。 |
All | predicate 指定して全部 true なら true。 |
Any | predicate 指定して全部 true じゃなけりゃ true。 |
AsEnumerable | シーケンスを LINQ to Objects で使える IEnumerable |
Average | そのまんま。 |
Cast | 全部を指定した型に変換。 |
Concat | シーケンス結合。 |
Contains | Python の in と同じ。 |
Count, LongCount | 個数カウント。 |
Distinct | 重複削除。 |
ElementAt | インデックス指定と同じだと思うけど……。 |
ElementAtOrDefault | ↑の、例外を返さない版。 |
Except | 指定したシーケンスにあるものを除く。 |
First | 最初。 |
FirstOrDefault | 見ての通り。 |
GroupBy | まとめる。このへんよくわからん。 |
Join | 組にする。このへん使い方よくわからん。 |
Last | 最後。 |
LastOrDefault | 見ての通り。 |
Max, Min | 最大と最小。 |
OfType | 指定の型だけにする。 |
OrderBy | 昇順。 |
OrderByDescending | 降順。 |
Reverse | 逆。 |
Select | 関数を通して項目を射影する……射影? |
SelectMany | 複数のソースコレクションを結合。どゆこと。 |
SequenceEqual | 指定したシーケンスと同じだったら true。 |
Single | 唯一の項目を出す。なかったり、2つ以上あったら例外。 |
SingleOrDefault | なかったときは null で2つ以上あったら例外。 |
Skip | 先頭から指定個数取り除く。 |
SkipWhile | predicate 指定して、それに一致する項目まで取り除く。 |
Sum | そのまんま。 |
Take | 指定個数取得。 |
TakeWhile | predicate 指定して、それに一致しなくなったとこ以降取り除く。 |
ToArray | ToDictionary, ToList 含めそのまんま |
ToLookup | 連想ルックアップ。何それ。 |
Union | 2つの入力の両方、もしくはどちらかにある項目。え? 結合して Distinct ってこと? |
Where | predicate に一致しない項目を除く。 |
Zip | Python の zip と同じ。 |
書くのスゲー疲れた。でもこういうのをざっと見るのって、 Python で itertools とか collections モジュールの中を見てるときみたいな、おもちゃ箱みたいな楽しさあるね。
小休憩
Python 内包表記をちょろっと書いてたけど、これ Python はじめたころはマジで意味不明だったのよな。
リスト内包表記をすると入れ子構造を凝縮できる!
と興奮したが俺の趣味の範囲ではいまのところ、for文でlist.append()を使うことが多いのでこれは大して使えんか。
「大して使えんか」……だと? 今となっては逆に append
は泣く泣く使うモノだ。むしろ my_append = lis.append
とかラップして使うモノだ。昔からみろりHP書いているおかげで、成長がこういうところでわかるぜ。
てか、ついに「これは C# のほうがつえーわ」ってやつが出てきちまったな……。