linq.js ver 1.0.0.1

更新内容

Viewsがあまりにも右肩下がりに、ゼロに届きそうな勢いなので追加燃料投下。焼け石に水、とも言う。Linq.Enumerableに「Choice, RangeTo, RangeDownTo」を追加しました。また、Cycleの引数に配列を入れることができるようになりました。そして、あまり、というか全く突っ込みがこなかったのでStableにしちゃいました。ああ、私もDisられたい。キャッキャウフフの夢は遠い。さて、で、以下に追加メソッドのサンプルを記します。

Choice

引数のものをランダムに、無限に繰り返し生成します。つまりCycleのランダム版です。

var TrueOrFalse = function(){return E.Choice(true,false).First()};
TrueOrFalse(); // true or false

例では、無限に生成される「True,False」の、先頭を取得することでTrueかFalseかがランダムに選択されます。関数でくるんでいるのは、var TrueOrFalse = E.Choice(true,false);で止めておいて、使う時はTrueOrFalse.First()にすることと同じなのですが、見栄えがいいかな、と、その程度の理由なのでどうでもいい話です。

var array = E.Range(1,6).ToArray();
var Dice = function(){return E.Choice(array).First()};
Dice(); // 1 or 2 or 3 or...6

もう一つ例として、Choiceでは配列を指定することもできます(Cycleも指定できるようになりました)。これでサイコロの出来あがり。サイコロ二つの値ならDice() + Dice()です。非常にお手軽。ただ、複数個なら……

E.Choice(E.Range(1, 6).ToArray()).Take(2).Sum();

Take + Sumを用いることで、大量の個数にも対応できるようになります。更に一つ、Choiceではないのですがサイコロ繋がりで例を出すと……

E.Repeat(E.Range(1, 6).ToArray(), 5).Flatten().Shuffle().ToArray()

ボードゲームに使う乱数は、ダイスを使った乱数(完全なランダム)と、カードを使った乱数(偏りのないランダム)がありますよね。いや、私はボードゲーム全然知らないのですけど、XBLAのCatanにそういうオプションがあったので。カードを使う、例えばトランプの1-13をダイス代わりに使うとすると(使ったカードは場に捨てる) 13x4回の間に必ず全てのカードが4回使われることになります。偏りがなくなるので有利不利が運に左右されにくくなり、またカード終番になると出目が予測できるので取り得る戦法も変わってきます。

というわけで、上記コードは6x5回分のサイコロの出目カードを作成。シャッフルする前にFlatten()で配列状態で送られてくる値を平らにしてやります。あとは、array.pop()あたりで値を取り除きながら取得して、空っぽになったら再生成することでカード乱数の出来あがり。

RangeTo / RangeDownTo

RangeTo(start,to)は「第一引数の値から第二引数の値まで生成」します。通常のRange(start,count)とはまた違った使い道があるかと思います。こちらのほうが素直に記述出来るケースがあったりと、使い分け、ですね。

E.RangeTo('a'.charCodeAt(0), 'z'.charCodeAt(0))
    .Select("String.fromCharCode($)").ToString();

結果は「abcdefghijklmnopqrstuvwxyz」という文字列。これだけじゃつまらないので、もう少しひねくれてみると……

var numbers = E.RangeTo(0, 9);
var alphabet = E.RangeTo('a'.charCodeAt(0), 'f'.charCodeAt(0)).Select("String.fromCharCode($)");
var digits = numbers.Concat(alphabet); // 0-9とa-fを連結する
// 直積で0-fの二桁全ての組み合わせを出す(00からff、256個)
var colors = E.From(digits).SelectMany(function(i)
{
    return E.From(digits).Select(function(j)
    {
        return i.toString() + j.toString();
    })
});
// R, G, Bにそれぞれ独立して割り振る
var R = colors.ToArray();
var G = colors.ToArray();
var B = colors.ToArray();

これで00からffまでの色コード配列がR,G,Bの3つ分できました。普通に書くと、それなりに長くなるんじゃないかと思えるので、こうして(分かりやすいかはともかくとして)サクッと記述出来るのは魅力的です。自分で言うなって話ですが、いや、LINQ自体が、ね。知れば知るほどC#のLINQは良く出来てるな―、と思います。上のコードはC#でも当然動かせます。ただ、C#は型が異なるものをConcatできないので、numbersの生成時にSelectでString型に変換、alphabetの生成時にint->char->stringに変換する必要がありますけど。

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var clone = E.From(array).ToArray();

そういえば、前回RepeatがいわゆるFillの代用になると書きましたが、From().ToArray()はシャローコピーの代用になります。あんまり派手なことに使わずに、地味にこそこそっと使うのがお薦め。派手にメソッドチェーン組み立てるのもお薦め。楽しいです、ほんと。

Profile

Yoshifumi Kawai

Cysharp, Inc
CEO/CTO

Microsoft MVP for Developer Technologies(C#)
April 2011
|
July 2023

Twitter:@neuecc GitHub:neuecc

Archive