2006-08-30

実践JavaScriptで配列をシャッフルする方法リファクタリング

JavaScriptで配列をシャッフルする話を見て、そういえばArray#shuffleは以前書いた記憶があるなーと思って調べてみたらコピペだった。
http://www.fumiononaka.com/TechNotes/Flash/FN0212002.html

Fisher-Yatesというアルゴリズムだそうです。
Array.prototype.shuffle = function() {
    var i = this.length;
    while(i){
        var j = Math.floor(Math.random()*i);
        var t = this[--i];
        this[i] = this[j];
        this[j] = t;
    }
    return this;
}
a = [1,2,3,4,5];
a.shuffle() // 3,1,5,2,4
a // 3,1,5,2,4

ごく普通に実装するとランダムに一件ずつ取り出すのがわかりやすいんじゃないかと思う。Rubyの本とか見ると大体そんな感じで書いてある気がする。JavaScriptには破壊的sliceがないので代わりにspliceを使えば良い。
Array.prototype.shuffle = function(){
    var len = this.length;
    var ary = this.concat();
    var res = [];
    while(len) res.push(ary.splice(Math.floor(Math.random()*len--),1));
    return res
}
a = [1,2,3,4,5];
a.shuffle() // 3,1,5,2,4
a // 1,2,3,4,5

元の配列には変更を加えず、ランダムに並べ替えられた新しい配列を返す。要素数の増減があるから遅くなるかも。ベンチ取ってないけど。

配列に独自のプロパティを持たせてあったり、toStringをインスタンス固有の関数に置き換えてある配列オブジェクトがあったとして、元のオブジェクトのまま中身をシャッフルしたい、という場合には、中身を直接入れ替えるのが良いでしょう。(最初に書いたやり方のように)

lazyな処理をしたい場合はランダムピック方式の方がやりやすい。巨大な配列をシャッフルしたい場合は、ランダムな順番で要素を返すイテレータを作るのがよいだろう。
Array.prototype.random_iter = function(){
    var len = this.length;
    var ary = this.concat();
    return {
        has_next: function(){
            return len ? true : false
        },
        next: function(){
            if(!len) return null;
            var i = Math.floor(Math.random() * len--);
            return ary.splice(i,1)
        }
    }
}

これなら一万件ぐらいの配列からでも高速に一件ずつ取り出すことができる。

あと配列をランダムに並べ替えるのにsortメソッドを使ってコンペア関数にランダムな値を返すようにする、という方式は片寄る、って話をしてて、なんで片寄るのかを少しわかりやすくしてみた。
http://la.ma.la/misc/js/randomize.html

端っこの要素があまり比較されないで片寄る様子がわかると思います。


なんか大した話でもないのに無理矢理発展させた感が否めない。

2006-08-28

AutoHotkeyを使ってFirefoxをリロードするだけのexeファイルを作ってみた

エディタの保存と同時にブラウザを自動でリロードさせると開発がはかどって素晴らしいよ、みたいな話をしてたら軽く派生したわけなんですが

自動リロードで開発をアジャイルにするたった一つの方法! < 31 < July < 2006 < nulog, NULL::something : out of the headphone
http://lowreal.net/logs/2006/07/31/1

hail2u.net - Weblog - CSSファイルを保存すると同時にブラウザをリロード
http://hail2u.net/blog/webdesign/save-css-file-and-reload-browser.html

WSHやRubyからキー操作を送るって方法だと、操作対象のウィンドウをアクティブにしないとキー操作を受け付けてくれなかったりして(もっといい方法あるのかも知れないけど)、一瞬だけどエディタからフォーカスが外れて気持ち悪かったりする。

AutoHotkey使うとバックグラウンドのウィンドウにもキー操作を送ることが可能で、こんな感じのスクリプトを書いて実行すると黙ってFirefoxをリロードすることができる。
http://la.ma.la/misc/ahktool/reload_firefox.ahk

中身はこれだけ。
#NoTrayIcon
SetTitleMatchMode, 2
WinGet, FF,, Mozilla Firefox
ControlSend,, {F5}, ahk_id %FF%

AHKの素晴らしいのは、書いたスクリプトを単体起動可能なexeファイルにコンパイルできること。AHKスクリプトのコンパイルは超簡単で、右クリックしてCompile Scriptを選ぶだけ。これだけでランタイム不要のexeファイルができあがります。189KBとサイズも軽量。ウィルスとか心配な人はAutoHotkeyをインストールして自分でコンパイルすると良いと思います。
http://la.ma.la/misc/ahktool/reload_firefox.exe

後はエディタの保存時にreload_firefox.exeが起動されるようにすればいい。萌ディタだったらこんな感じでsrcfile.javascript.txtなんかに記述する。
f.onSave = function(){
    var wsh = new ActiveXObject("WScript.Shell");
    wsh.Run("c:\\ahktool\\reload_firefox.exe", 0);
}

SleipnirもAPIを使わないでこれと同じ要領でいける。Operaは何故かうまくいかなかった。

参考:AutoHotkeyを流行らせるページ
http://lukewarm.s101.xrea.com/

2006-08-19

IEはwindow.openでリファラを送らない

IE系のブラウザはwindow.openで開いたページに対してはリファラを送りません。
例えばlivedoor readerのP+OとかVとかで開いた記事についてはリファラが残りません。なので、アクセス元の統計なんかには気持ち少なめに出るんじゃないかと思います。マウスを使ってるユーザーの分はカウントされますが、IE系のブラウザでショートカットキーで操作しているユーザーの分はカウントされません。

内輪なページからのリファラ隠しにwindow.openを使ってたりしたこともあるのですが、他のブラウザだと普通に送るので使えません。

まあだからどうしたという話ではあるのですが。
IE7でも送らないみたいです。

2006-08-18

Operaのアドレス帳をvCardにするツール、JavaScriptで

Operaのアドレス帳ってエクスポートしてもOperaでしかインポートできないような気がしたので作ってみた。
テンプレートいじればCSVとかにも変換できると思います。
http://la.ma.la/misc/js/adr2vcard.html

こういうファイルの形式変換みたいなウェブサービスやったら流行るんじゃないかと思ったけどメールアドレス収集みたいなことができるからやりたくないと思った。

だからJavaScriptで作るわけだけど。

ページ内のフォームのmethodを全てGETにするブックマークレット

ページ訪問者数の男女比を調べるサービス
http://adlab.microsoft.com/DPUI/DPUI.aspx

なんてのがあって、少し前にあれこれURL入れて遊んだりしてたんだけど、結果にリンクが張れないのが難点で、これはPOSTメソッドでフォーム送信しているからなんだけれど実際のところGETでも動いたりする。
なのでFirebugでごにょごにょやったり、Web Developer Extensionでフォームのメソッド変える機能があるのでGETにすればリンクを張れるようになるんだけど汎用的にブックマークレットにしてみた。

フォームをGETに

2006-08-17

はてなアンケートの集計を視覚化するGreasemonkeyスクリプト

Web プログラマの方にアンケートです。現在仕事で使っている言語と、一番好きな言語を教えてください
http://q.hatena.ne.jp/1155781580

という質問があったので、さくっとGreasemonkeyでビジュアライズするスクリプトを書いてみた。
http://la.ma.la/misc/userjs/hateqvisualcell.user.js

横軸に好きな言語で集計

python好きの人はpythonで仕事してるみたいです。

横軸に仕事で使ってる言語で集計


おおむね仕事で使ってる言語が好きみたいですが、JavaScript使いはPHPが好きみたいです。
使ってる言語の方は複数回答なので、PHPプログラマがついでにJavaScriptを書かされてるんじゃないかと予想。

沖縄ではPHPしか使われてないとか、C#使いはC#が好き(一名)とか、母数が少ないのでよくわかりません。