概要

ちらっと見たら 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; }
  • 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()を使うことが多いのでこれは大して使えんか。

Mark Lutz『初めてのPython』つづき

「大して使えんか」……だと? 今となっては逆に append は泣く泣く使うモノだ。むしろ my_append = lis.append とかラップして使うモノだ。昔からみろりHP書いているおかげで、成長がこういうところでわかるぜ。

てか、ついに「これは C# のほうがつえーわ」ってやつが出てきちまったな……。