Sumを用いることで、大量の個数にも対応できるようになります。5).Flatten().Shuffle().ToArray()ボードゲームに使う乱数は、ダイスを使った乱数(完全なランダム)と、カードを使った乱数(偏りのないランダム)がありますよね。いや、私はボードゲーム全然知らないのですけど、XBLAのCatanにそういうオプションがあったので。13x4回の間に必ず全てのカードが4回使われることになります。偏りがなくなるので有利不利が運に左右されにくくなり、またカード終番になると出目が予測できるので取り得る戦法も変わってきます。いうわけで、上記コードは6x5回分のサイコロの出目カードを作成。シャッフルする前にFlatten()で配列状態で送られてくる値を平らにしてやります。あとは、array.pop()あたりで値を取り除きながら取得して、空っぽになったら再生成することでカード乱数の出来あがり。RangeDownToRangeTo(start,to)は「第一引数の値から第二引数の値まで生成」します。通常のRange(start,count)とはまた違った使い道があるかと思います。こちらのほうが素直に記述出来るケースがあったりと、使い分け、ですね。.Select("String.fromCharCode($)").ToString();結果は「abcdefghijklmnopqrstuvwxyz」という文字列。colors.ToArray();これで00からffまでの色コード配列がR,G,Bの3つ分できました。普通に書くと、それなりに長くなるんじゃないかと思えるので、こうして(分かりやすいかはともかくとして)サクッと記述出来るのは魅力的です。自分で言うなって話ですが、いや、LINQ自体が、ね。知れば知るほどC#のLINQは良く出来てるな―、と思います。上のコードはC#でも当然動かせます。C#は型が異なるものをConcatできないので、numbersの生成時にSelectでString型に変換、alphabetの生成時にint->char->stringに変換する必要がありますけど。E.From(array).ToArray();そういえば、前回RepeatがいわゆるFillの代用になると書きましたが、From().ToArray()はシャローコピーの代用になります。派手なことに使わずに、地味にこそこそっと使うのがお薦め。派手にメソッドチェーン組み立てるのもお薦め。サンプルサンプル2009-04-08前回投稿したlinq.js、誰の目にも触れず埋もれてしまうのではないかと思っていたのですが、ある程度は見てもらえたようでホッとしました。表作ったり動画作ったりと、ゲーム攻略サイトのノリで書き上げたかいがありました(そして、もうすっかりゲームサイトじゃなくなってしまった!)。ここ数日に新しく登録されたCodePlexのプロジェクトで見ても、Views/Downloads共に多いほうのようです。いってもDLは30前後なので、感覚的には全然少ないのですが。そもそもJavaScriptで野良ライブラリを使うシチュエーションなんてないだろ常識的に考えて......といったところなのでしょうがない。前回は完全にチュートリアルだったので、今回はちょっと実用っぽいサンプルで行きます。100).ToArray();RepeatはC#ではイマイチ使い道が見つからないんですが、JavaScriptでは激しく便利なよう。Padで動かしながら作れます。a-zの生成は頭の中で作ってたモノはちょっと違ってて反応みながら即座に直してました。リアルタイムで反映されると便利。JavaScriptはIntelliSenseがないので、細かいミスが多くなってしまうので(charCodeFromだと思ってたんですよー)そういえば、a-zの生成の26という数字は良くない。'z'.charCodeAt(0)を使いたいのですが、Rangeの二つ目はcountなので、(z-a+1)を書かなくてはいけなくて、少し長くなるかなあ。「第二引数の数字まで生成」も用意しておくべきでした。近いうちに追加しておきます。E.ToInfinity('a'.charCodeAt(0)).TakeWhile("$<='z'.charCodeAt(0)")で結果は同じになりますけど、無駄があるかなあ。TakeWhileは加工した後のものに使いたいのであって、生成のすぐ後に使うのは違和感がある。.Take(100)更に応用して、100個ランダムなa-z,A-Zのアルファベットを生成する、というもの。Selectを繋げていっての加工は楽しくて簡単。生成後はToArray()で配列にするのも、ToString()で文字列にするのも、好きに選べます。終了条件を今回はTake(100)にしましたが、TakeWhileで条件をつけるのが自然。画面を埋め尽くしたら終了とか。'A'));文字を数字と見なしての生成はC#のLINQでも便利に使えます。C#だとこんな感じでしょうか。Random()としたいところなのですが、それだと二個目のSelect時にはRandomが消滅しているので使えないので、しょうがなく。'A'));最初のSelectの段階でランダムも保持しておけば解決。素直に外出しのほうがいいかなあ、という気もします。この辺、どっちにすべきか微妙に悩ましい。この程度の場合ならSelectを二段にせず、一段階目で全部処理してしまえば万事解決な気はします。個人的には多段階に繋いでこそのLINQであり浪漫だと思うのだけど......。結果例0:4981:8882:8083:13454:10335:11196:8977:12148:11709:1028*/初期化と書き出しにだけlinq.jsを使いました。比較関数にランダムはダメ・絶対。こんな感じに、地味にコソコソっと普通のJavaScriptコードに混ぜ込んでも便利に使えるんじゃないかなあ、と思います。私自身は、もうこれなしだとJavaScript書く気になれない、のですがそもそも全然JavaScriptで何も書いちゃあいないので何とも言えなかったり。あと一回分はアップデートネタがあるので、今週末にでも追加します。Objectsを実現するライブラリ。10).Where("$%3==0").Select("$*10");こんな風に記述できます。この例は1から10の整数を発生させ、そのうち3で割り切れる数を10倍にするというもので、結果は30,60,90になります。Objectsは、強力なリスト操作ライブラリ群とでも思えば大体あってる、かな?C#とは縁のない人でも、便利に使えると思います。LINQに対するアプローチは色々あるようですが、私はド直球にメソッド構文を実現することを目指しました。LINQの特徴として多く紹介されているクエリ構文を実現しようとすると、ただ煩雑になるだけで実用的なメリットはないからです。実用性を第一に考えました。そのため、無名関数をラムダ式風の文字列で記述可能にし、また、幾つかの短縮記法を設けてあります。JavaScripterのための簡易説明index付きのforeachが書け、IEでmapやfilterやreduceが使える。非破壊的なsortやremoveができる。DOMに対しても同じようにforeachやmapを適用できる。shuffle(ランダムに並びかえ)やdistinct(重複除去)など、便利メソッド集として使える。メソッドチェイン形式でシーケンスを加工していくことができる。Referenceを参考にしてください。文字列によるラムダ式の記述では、複数引数時でもカッコは必要ありません(つけても問題ありません)。引数がゼロ個の場合は、C#ではダミーとして「_」を使ったりしますが、linq.jsの場合は=>も書く必要がありません。1000).Select("Math.random()")」などと記述することで、for文の代用として動かせたりします。ラムダ式には幾つかの省略記法を用意してありますが、それは後述します。匿名型、的なものは、JavaScriptの文法に則りオブジェクトを作ることで解決します。newは必要なく{key:value,key:value}と書くことで匿名型と同様の動きをします。キーの省略は出来ません。ToDictionaryはありません、かわりにToObjectがあります。違いは、重複したキーが挿入されても例外を吐かず、上書きされます。一つ、基本的にメソッドは例外を吐きません。First(predicate)で何も見つからなかった場合は例外ではなくnullを返します。唯一例外を吐くメソッドはSingle/SingleOrDefaultだけです。Cast,OfType以外のメソッドは全て実装してあり、また、EqualityComparerを除けばオーバーロードも標準通りに従っています。実行時動作もC#と同じ、はずです(違う挙動を示す場合は教えてください)。TraceF」といったメソッドが定義されています。容易に新しいメソッドを拡張メソッドのように追加することが出来ます。生成linq.jsを読み込むとLinqという名前とEという名前を占有します。EはLinq.Enumerableのショートカットになっています(jQueryなどの$と同じように、よく使うものなので短縮名を付けてあります)。linq.jsの動作は全てLinq.Objectの連鎖で実現されますが、そのLinq.Objectの生成をLinq.Enumerable以下のメソッドが担当します。生成メソッドは色々あるのですが、詳しくはリファレンスを参照ください、ということでここでは最も使うFromとRangeの解説をします。55Range(start,count)はstartの値からcountの個数分だけ整数を生成します。この例では1から10個分、10までです。E.Range(5,2)とすれば、5から2つ分で5,6が生成されることになります。Rangeメソッドが返すものは配列ではなくLinq.Objectなのでメソッドを繋げていくことが出来ます。宣言段階では値の生成は始まらず、ToArray(配列に変換)など具体的なオブジェクトへの変換メソッドや、Sumなどの数値集計メソッドが実行される時に値の生成が始まります。このことは以降、SelectやWhereメソッドの解説をする時にまた詳しく解説します。E.Repeat("hoge",1)と等しいです配列やオブジェクトからLinq.Objectを生成するにはFromを使います。配列の場合は直感的に分かりやすくそのまんま順番通りに値を列挙していくのです、が、関数は自動で除去されます。seq1は"aaa",{hoge:"tako"},1という値が生成されることになります。オブジェクト/連想配列を入れると特殊な動作が入ります。値が関数のものは除去される、というのは配列と同じなのですが、プロパティをKeyに、値をValueに格納したオブジェクトが列挙されます。seq2は{Key:a,Value:312},{Key:c,Value:931}という値が生成されることになります。この動作はC#のDictionary(型付き連想配列)の動作(KeyValuePairが列挙される)を模しています。Fromには数字や文字列を入れることも可能です。その場合は値を一度だけ送る、つまりRepeat(value,1)と等しくなります。オブジェクトに対してLINQを使いたいけれどKeyValuePairに変換したくない、という時はRepeat(obj,1)とすることで回避出来ます。Repeatの詳しい使い方はリファレンスを参照してください。C#標準と違い、回数指定を省くと無限リピートになります。射影とラムダ式シーケンスの中身に関数を適用して変形する。他の言語ではmap関数として定義されていることが多いっぽいのですが、LINQではSelectメソッドがそれです。10})1から10を生成→その数値を10倍。いうことで結果は10,20,...,100です。文字列に変形させることも、オブジェクトに変形させることもできます。LINQはSelectに限らず無名関数を多用します、が、JavaScriptではfunction(){return}と書かなければならなくて記述が面倒くさい。いうことで、文字列でC#のラムダ式のようなものを記述出来るようにしました。"outer,inner=>outer*inner");ラムダ式は、=>の左が引数、右が式として評価されます。引数が一つの場合、=>を省くと$がその引数のかわりになります。プロパティへのアクセスも普通の引数を使うときと同じように「"$.hoge"」などでアクセスできます。Joinなど、"x=>x"を書く必要がある場合のための省略記法として""を用意してあります。x}に等しいことになります。ラムダ式をネストする際、前のラムダ式の変数は参照出来ません。何のこっちゃって感じですが、同梱のsample.htmの一番下のコードを見てください。その場合、無名関数を用いることで参照することができます。抽出・テストフィルタリングもSelectと同様に多用するメソッドです。他の言語ではfilterとして定義されていることが多いっぽいですが、LINQではWhereメソッドがそれです。.Select("$*10")1-10のうち3で割り切れる数のみを通して、10倍する。30,60,90が結果。挟んでいるTraceとは何かというと、そこを通っている値を画面に出力します(document.writeで書き出しているので、あまり実用性はありません、TraceFメソッドを用いるとFirebugのコンソールに出力できます)。30といった感じに値が流れている様子が確認出来ます。E.Range(1,10)は10個の値を全て生成してからWhereに渡しているのではなく、一つ一つ生成して終わりまで通しています。E.ToInfinity().Where("$*$*Math.PI>10000").First()例えば、面積が10000を超える最初の半径は幾つ?といったように、どこまで値を生成すればいいのか分からない問題に効果を発揮します。無限生成系は条件指定によっては永遠に止まらないものが出来てしまいますので注意してください。First(最初を取得)やTake(個数を指定して取得)は止まりますが、Last(最後のものを取得)やSingle(唯一の要素を取得)は絶対に止まりません。「最後」を得るために、「唯一」であることを確認するために生成が終わるまでループを回し続けるからです。以上で基本は終了です。同梱してあるsample.htmには、ひねくれた実例なども収録してあるのでご参照ください。Padはリアルタイムに動作を確認することが出来ますので、R.Range(0,10)辺りで数字を生成して遊んでみてください。動画の例はランダムソート(笑)の検証と同じものになっています。0-10を生成してシャッフルして先頭を取り出したものを→キーを自身・値を自身にしてグループ分けして集計のキーをkey・集計の個数をcountというプロパティに格納したオブジェクトに変換して→keyの順番で昇順にソートして→書きだす。Objectsに関するドキュメントが参考になるかと思います。標準クエリ演算子の概要とか。Objects用コードもそのまま動かせるはず、です。実行効率......考えたら負けかな、と思っている。そんな派手なことやらなければ誤差範囲に収まる、といいなあ。ソースへ、厳しい突っ込みが貰えたら嬉しいなあ、と思っています。内心、こういうコードでいいのか不安でいっぱいなので。C#って日本のネット上では地味な存在だけど、linq.jsが架け橋になって、C#にも興味を持ってもらえたらなあ、なんて思いつつ、とりあえず、試してみてもらえると嬉しいです。JavaScript2009-04-02LINQPadのように気楽に入力して動作確認。JavaScript上で動かせると超お手軽で、確認が楽ちんでいいですね。LINQも正規表現のようにリスト操作用DSLと考えてみれば、こうやって即時評価できるチェッカーの便利さも納得。個人的にはこれだけでも作って良かったな、と思えています。JavaScriptで一番使う列挙可能な物体といったらDOMなので、ちゃんとNodeListも扱えるようにしました。LINQPad上でもプロパティとキーを画面に出したりして動かせます。コード例は、outerHTMLがタグを吐くせいで、この画面上だとエラー出るのでWhereで除外しました。し時の引数識別子は「x」ということにしているのだけど、$のほうが自然かなあ。変えるなら今のうちというか今を逃したら変えられないというか。$を使うとjQueryと衝突しそうなイメージが出るような気がして若干気が引ける(実際は全くそんなこたぁありません)。逆にメソッドチェーンだらけだし、見た目がjQueryっぽくなって受け入れられやすくなる、気もする。DL数一桁で終わるであろう現実を見ていません現在の作業状況としては、リファレンス書きが終わって、あとは英語でチュートリアル書くだけなんですが英語書けないので諦めようかと思案中。別にCodeplexだからって英語で書かなくてもいいぢゃない。諦めるを選べば、今週中に公開出来そうです。諦めないを選べば永遠に公開出来なさそうです。https://github.com/neuecc/Blog2。