JavaScript: documentの比較に関するメモ

Googleで「mdc」と検索した結果の1ページ目と2ページ目のそれぞれで

$g('/descendant-or-self::*', null, getElementXPath)

した後

p2.filter(function(v){return (p1.indexOf(v) === -1);}).join('\n')

して新しく増えたノードを調べた。


id("res")/div[1]/div[1]/h2[1]/a[1]/b[2]
id("res")/div[1]/div[1]/h2[1]/a[1]/b[3]
id("res")/div[1]/div[1]/nobr[1]
id("res")/div[1]/div[1]/nobr[1]/font[1]
id("res")/div[1]/div[1]/nobr[1]/font[1]/a[1]
id("res")/div[1]/div[1]/nobr[1]/font[1]/a[1]/font[1]
id("res")/div[1]/div[1]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/span[1]/b[1]
id("res")/div[1]/div[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/wbr[1]
id("res")/div[1]/div[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/span[1]/b[1]
id("res")/div[1]/div[4]/h2[1]/a[1]/b[1]
id("res")/div[1]/div[4]/nobr[1]
id("res")/div[1]/div[4]/nobr[1]/font[1]
id("res")/div[1]/div[4]/nobr[1]/font[1]/a[1]
id("res")/div[1]/div[4]/nobr[1]/font[1]/a[1]/font[1]
id("res")/div[1]/div[4]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[2]
id("res")/div[1]/div[4]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[3]
id("res")/div[1]/div[4]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[4]
id("res")/div[1]/div[5]/h2[1]/a[1]/b[2]
id("res")/div[1]/div[7]/h2[1]/a[1]/b[1]
id("res")/div[1]/div[7]/nobr[1]
id("res")/div[1]/div[7]/nobr[1]/font[1]
id("res")/div[1]/div[7]/nobr[1]/font[1]/a[1]
id("res")/div[1]/div[7]/nobr[1]/font[1]/a[1]/font[1]
id("res")/div[1]/div[7]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[1]
id("res")/div[1]/div[7]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[2]
id("res")/div[1]/div[8]/nobr[1]
id("res")/div[1]/div[8]/nobr[1]/font[1]
id("res")/div[1]/div[8]/nobr[1]/font[1]/a[1]
id("res")/div[1]/div[8]/nobr[1]/font[1]/a[1]/font[1]
id("res")/div[1]/div[8]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[1]
id("res")/div[1]/div[8]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[2]
id("res")/div[1]/div[8]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[3]
id("res")/div[1]/div[8]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/b[4]
id("res")/div[1]/div[8]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/span[1]/b[1]
id("res")/div[1]/div[9]/nobr[1]
id("res")/div[1]/div[9]/nobr[1]/font[1]
id("res")/div[1]/div[9]/nobr[1]/font[1]/a[1]
id("res")/div[1]/div[9]/nobr[1]/font[1]/a[1]/font[1]
id("res")/div[1]/div[10]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/span[1]/wbr[1]
id("res")/p[1]
id("res")/div[2]
id("res")/div[2]/table[1]
id("res")/div[2]/table[1]/tbody[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[2]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[2]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[2]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[3]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[3]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[3]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[4]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[4]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[4]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[5]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[5]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[5]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[6]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[6]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[6]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[7]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[8]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[8]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[8]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[9]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[9]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[9]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[10]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[10]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[10]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[11]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[11]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[11]/font[1]/a[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[12]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[12]/font[1]
id("res")/div[2]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[2]/span[12]/font[1]/a[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[1]/a[1]
id("np")
id("navbar")/table[1]/tbody[1]/tr[1]/td[1]/a[1]/span[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[1]/a[1]/span[1]/b[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[2]/a[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[2]/a[1]/div[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[2]/a[1]/span[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[3]/span[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[12]/a[1]/div[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[13]
id("navbar")/table[1]/tbody[1]/tr[1]/td[13]/a[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[13]/a[1]/span[1]
id("navbar")/table[1]/tbody[1]/tr[1]/td[13]/a[1]/span[1]/b[1]

id関数を使わないようにして、全部に共通するprefix(/html/body/...)を削った後、一番多い頭を取る……しんどいな。

JavaScript: 普通に同期処理

var defer = function(/* f1, f2, ... */){
    var self = this, fn = Array.prototype.slice.call(arguments);
    (function(/* arg2, arg3, ... */){
        var args = Array.prototype.slice.call(arguments);
        (fn.shift()).apply(self, [arguments.callee].concat(args));
    })();
};

defer(function(next){
    var t=1;
    alert(t);
    window.setTimeout(function(){ next(t+1); }, 1000); // 1秒後に第2引数を2として次の関数を呼ぶ
}, function(next,t){
    alert(t);
    window.setTimeout(function(){ next(t+1); }, 1000);
}, function(next,t){
    alert(t);
    window.setTimeout(function(){ next(t+1); }, 1000);
}, function(next,t){
    alert(t);
});

前エントリのyieldっぽいことを配列とコールバック関数でやってみたメモ。

案外、これで十分かも。

JavaScript: yieldで同期処理

New in JavaScript 1.7 - MDC

JavaScript1.7 の yield を使って、非同期処理を同期処理のように書く方法 - IT戦記

// ==UserScript==
// @name           defer
// @namespace      http://mayokara.info/
// @description    sample script
// @include        http://*
// ==/UserScript==

(function(cdata){
    // type指定しないとyieldが使えない
    var s = document.createElement("script");
    s.type = "application/javascript;version=1.7";
    s.textContent = cdata.toString();
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(s);
    head.removeChild(s);
})(<><![CDATA[

var defer = function(F){
    var g = F(function(t){
        try { g.send(t); } catch(e) {}
    });
    g.next();
};

defer(function(next){
    alert(1);
    window.setTimeout(next, 1000); // 1秒後にnextを呼ぶ
    yield; // next来るまで待機
    alert(2);
    window.setTimeout(next, 1000);
    yield;
    alert(3);
    window.setTimeout(next, 1000);
    yield;
    alert(4);
});

]]></>);

Firefox2でも動く。

というか、Firefox3のuser.jsでもtype指定しないとyield使えないのか……


「IT戦記」のサンプル同様、nextの引数にXHRのresponseTextを与えれば、yieldの値としてそれをキャッチできる。

Greasemonkey: koko-de-yomu.user.js

アンカー・ドラッグ・オープンの図

koko-de-yomu.user.js


アンカーを引っ張るとその場にiframeを開くuser.js。

開いた後は、iframe外のクリックで消す。


便利かどうかは、まだ判断しかねる感じ。

デフォルトの挙動を潰すので、タブバーに引っ張っていって開くとかができなくなる。CTRL/SHIFT/ALT/METAを同時押しで発火しないようにしました。

というか、誰か作ってたような気がするんだけど、気のせいなのか見つからない……


あと、iframe.src = hrefでURLをセットすると、href === location.hrefのときに理由はわからないけど、エラーになる。

iframe.contentWindow.location.href = hrefとすると、うまくいく。

Fw: Mersenne Twister in JavaScript

Mersenne Twister in JavaScript

そりゃーあるわな。


Math.random() support, lifted from java.util.Random.java.

http://mxr.mozilla.org/js/source/js/src/jsmath.c#370

クラスでは 48 ビットのシードを使い、このシードは線形合同法で変更されます。

Random (Java 2 Platform SE 5.0)

SpiderMonkeyのMath#randomは48ビット線形合同法。

Fw: JSON Diff

JSON Diff

DOMツリーをJSON化して、これに食わせるって手もあるか。

というか、2つのdocumentのdiffを取るアルゴリズムを考えるべきか。

JavaScript: ベイズフィルタ

Naive Bayes classifier - Wikipedia, the free encyclopedia

var BayesFilter = function(aMemory){
    this._memory = aMemory || { t: 0, f: 0, prior: {} };
};
BayesFilter.prototype = {
    getMemory: function(){
        return this._memory;
    },
    train: function(bool, params){
        this._memory[bool ? "t" : "f"]++;
        params.forEach(function(v){
            if (!this._memory.prior[v]) {
                this._memory.prior[v] = { t: 0, f: 0 };
            }
            this._memory.prior[v][bool ? "t" : "f"]++;
        }, this);
    },
    classify: function(params){
        var t = this._memory.t, f = this._memory.f;
        var r = function(pt, pf){
            var x = (pt/t) || 1e-12;
            var y = (pf/f) || 1e-12;
            return Math.log(x/y);
        };
        var likelyhood = Math.log(t/f);
        params.forEach(function(v){
            likelyhood += this._memory.prior[v] ? r(this._memory.prior[v].t, this._memory.prior[v].f) : 0;
        }, this);
        return likelyhood;
    },
};
const KURENAI = ["栗林みな実", "菊田大介", "R・O・N", "新谷良子", "#1~#7", "#9~#11", "#8", "片山憲太郎", "スーパーダッシュ文庫", "集英社", "山本ヤマト", "松尾衡", "山崎みつえ", "石井久美", "荒井和浩", "佐々木研太郎", "藤純", "古市祐一", "大熊義明", "田村ゆり", "村松健", "山田稔", "中野徹", "HALF H・P STUDIO", "ブレインズ・ベース", "「紅」", "製作委員会", "ポニーキャニオン", "読売広告社", "沢城みゆき", "悠木碧", "升望", "真田アサミ", "木村はるか", "石毛佐和", "大久保藍子", "黒田崇矢", "植田佳奈", "岡本信彦"];
const TOLOVERU = ["矢吹健太朗", "長谷見沙貴", "週刊少年ジャンプ", "集英社", "加戸誉夫", "大和屋暁", "岡勇一", "松村拓哉", "わたなべけいと", "伴夏代", "工藤友紀", "渡辺直樹", "三間雅文", "渡辺剛", "ミュージックブレインズ", "XEBEC", "エイベックス・エンタテインメント", "ジェネオンエンタテインメント", "とらぶる製作委員会", "TBS", "thyme", "清水哲平", "THYME", "伊藤正恵", "佐々倉有吾", "Anna", "BON-BON BLANCO", "渡辺明乃", "戸松遥", "矢作紗友里", "新井里美", "子安武人", "花澤香菜", "川澄綾子", "名塚佳織", "大浦冬華", "吉野裕行", "柚木涼香", "千葉千恵巳", "橋本まい", "水橋かおり", "緒方賢一", "城雅子", "福圓美里"];
const OINARISAMA =["柴村仁", "放電映像", "岩崎良明", "吉田玲子", "新田靖成", "コロムビアエンタテインメント", "ZEXCS", "我が家のお稲荷さま。製作委員会", "松井五郎", "大川茂伸", "藤田淳平", "Elements Garden", "ヒトミソラ", "山本健太郎", "梅堀淳", "コウ", "早見沙織", "ゆかな", "中村悠一", "水島大宙", "嶋村侑", "鹿野優以", "伊藤静", "小野大輔", "水橋かおり", "堀江由衣", "浅野真澄", "吉田仁美", "浅川悠", "釘宮理恵"];
const KYOURAN = ["日日日", "黒田やすひろ", "池田眞美子", "x6suke", "古賀誠", "館藤健一", "SEE THROU STUDIO", "鎌田千賀子", "菅原徹", "スタジオコスモス", "武宮むつみ", "明田川仁", "菊谷知樹", "伊藤善之", "ランティス", "ノーマッド", "超常現象対策局分室", "バンダイビジュアル", "エンターブレイン", "ムービック", "み~こ", "柏森進", "MOSAIC.WAV", "畑亜貴", "浅野実希", "村井大", "乱崎凶華", "藤村歩", "tvk", "東海テレビ", "テレ玉", "テレビ大阪", "チバテレビ", "AT-X", "TVQ九州放送", "テレビ新広島", "福本公四郎", "米田行弘", "乱崎月香", "佐藤利奈", "伊藤真澄", "Ballet Mechanique", "乱崎優歌", "花澤香菜", "金井江右", "乱崎帝架", "安元洋貴", "ツキダタダシ", "乱崎雹霞", "広橋涼", "松井望", "乱崎凰火", "近藤孝行", "近藤昭雄", "乱崎銀夏", "藤田圭宣", "橋本由香利", "乱崎千花", "戸松遥", "後藤邑子", "中原麻衣", "森永理科", "喜多村英梨", "皆川純子", "清水愛", "斎藤桃子", "釘宮理恵", "石川英郎", "井上麻里奈", "下屋則子", "日野聡", "川澄綾子", "川田紳司", "水沢史絵", "五十嵐裕美", "寿美菜子"];
const MAIDGUY = ["赤衣丸歩郎", "月刊ドラゴンエイジ", "富士見書房", "迫井政行", "ふでやすかずゆき", "あおい小梅", "大塚美登理", "渡辺和夫", "岡本有香", "アトリエブーカ", "上村修司", "松井伸哉", "木村佳史子", "高桑一", "大久保薫", "神南スタジオ", "マッドハウス", "IMAGIN", "ジェネオンエンタテインメント", "フロンティアワークス", "AT-X", "金羊社", "ACG", "KOTOKO", "C.G mix", "三重野瞳", "福山芳樹", "F-BAND", "小山力也", "井口裕香", "豊口めぐみ", "阪口大助", "加藤英美里", "小林ゆう", "甲斐田裕子", "岡寛恵", "神田朱未", "藤田咲", "麦人"];
const MONOCHROME = ["空廼カイリ", "月刊コミックブレイドアヴァルス", "マッグガーデン", "紅優", "河原ゆうじ", "須賀重行", "桑原悟", "西表美智代", "中村昌樹", "後藤正浩", "鶴岡陽太", "楽音舎", "阿保剛", "村上純", "5pb.", "GENCO", "A.C.G.T.", "プロジェクトモノクローム", "KOKOMI", "黒瀬圭亮", "Asriel", "松澤由美", "清水永之", "昶&賢吾", "小野大輔", "神谷浩史", "諏訪部順一", "浅野真澄", "斎賀みつき", "小西克幸", "羽多野渉", "置鮎龍太郎", "田村ゆかり", "吉野裕行"];
const VAMPIRE = ["樋野まつり", "月刊LaLa", "白泉社", "佐山聖子", "岡田麿里", "西田亜沙子", "伊東和宏", "もちだたけし", "森下成一", "郷田ほづみ", "羽毛田丈史", "アニプレックス", "スタジオディーン", "NAS", "「ヴァンパイア騎士」", "製作委員会", "mavie", "黒須克彦", "h-wonder", "ON/OFF", "分島花音", "Mana", "堀江由衣", "宮野真守", "岸尾だいすけ", "千葉進歩", "福山潤", "諏訪部順一", "保志総一朗", "皆川純子", "喜多村英梨", "水野理紗", "安元洋貴", "中原麻衣", "折笠富美子"];
const AMATSUKI = ["高山しのぶ", "コミックZERO-SUM", "一迅社", "古橋一浩", "鈴木知恵子", "田頭しのぶ", "番由紀子", "小山俊久", "北爪英子", "飯田里樹", "福原まり", "フロンティアワークス", "スタジオディーン", "千歳コーポレーション", "園田凌士", "鈴木マサキ", "藤間仁", "Elements Garden", "カンノユウキ", "岩里祐穂", "梶浦由記", "坂本昌之", "引田香織", "福山潤", "遊佐浩二", "朴璐美", "諏訪部順一", "中田譲治", "野島健児", "森久保祥太郎", "小杉十郎太", "鈴村健一", "松岡由貴", "井上麻里奈", "大川透", "桐井大介", "小林ゆう", "成田剣", "三宅健太", "田中敦子", "五十嵐麗"];
const CODEGEASSR2 = ["内田健二", "竹田靑滋", "川城和実", "大河内一楼", "谷口悟朗", "CLAMP", "木村貴宏", "安田朗", "中田栄治", "阿久津潤一", "ビークラフト", "寺岡賢司", "吉野弘幸", "村田和也", "千羽由利子", "中谷誠一", "菱沼由典", "岩沢れい子", "大矢創太", "森田清次", "浦上靖夫", "井澤基", "中川幸太郎", "黒石ひとみ", "石川吉元", "ビクターエンタテインメント", "外村敬一", "ソニー・ミュージックエンタテインメント", "真野昇", "サンライズ音楽出版", "諸冨洋史", "河口佳高", "峯岸卓生", "湯川淳", "サンライズ", "毎日放送", "コードギアス製作委員会", "ORANGE RANGE", "福山潤", "水島大宙", "ゆかな", "小清水亜美", "高田裕司", "千葉紗子", "私市淳", "島香裕", "二又一成", "真殿光昭", "田中一成", "加瀬康之", "杉山紀彰", "中田譲治", "かないみか", "倉田雅世", "新井里美", "折笠富美子", "大原さやか", "後藤邑子", "櫻井孝宏", "保志総一朗", "渡辺明乃", "若本規夫", "名塚佳織", "幸野善之", "白鳥哲", "井上喜久子", "井上倫宏", "山野井仁", "寺島拓篤", "五王四郎", "幹本雄之", "佐藤正治", "宝亀克寿", "三宅ひとみ", "緑川光", "松元環季", "関根信昭", "松本大", "冨澤風斗", "成田剣"];
const SEKIREI = ["極楽院櫻子", "ヤングガンガン", "スクウェア・エニックス", "草川啓造", "吉岡たかを", "友岡新平", "東潤一", "泉寛", "甲斐けい子", "篠原愛子", "中山敦史", "布施由美子", "野尻由紀子", "ウィンズ", "佐野広明", "明田川仁", "マジックカプセル", "高梨絵美", "eNa", "グロービジョン", "セブン・アークス", "アニプレックス", "ムービック", "早見沙織", "月海", "井上麻里奈", "草野", "花澤香菜", "遠藤綾", "立花慎之介", "大原さやか", "甲斐田ゆき", "小西克幸", "甲斐田裕子", "根谷美智子", "生天目仁美", "ゆかな", "朴璐美", "福山潤", "関俊彦", "伊藤美紀", "阿澄佳奈", "石塚さより", "小林ゆう", "矢作紗友里"];
var bf = new BayesFilter();
bf.train(true, KURENAI);
bf.train(true, TOLOVERU);
bf.train(true, OINARISAMA);
bf.train(true, KYOURAN);
bf.train(true, MAIDGUY);
bf.train(false, MONOCHROME);
bf.train(false, VAMPIRE);
bf.train(false, AMATSUKI);
bf.train(false, CODEGEASSR2);

bf.classify(SEKIREI);
// -> 24.05411323618683

bf.classify(["花澤香菜"]); // +TOLOVERU +KYOURAN
// -> 26.937873935368604

bf.classify(["後藤邑子"]); // +KYOURAN -CODEGEASSR2
// -> 5.551115123125783e-17

bf.classify(["大原さやか"]); // -CODEGEASSR2
// -> -26.021583203494448

正ならtrueクラス、負ならfalseクラス。

Laplacian correctionのことは考えてないので、データが十分に多い場合はclassifyメソッドを適当に書き換えてください。

JavaScript: Array.prototype.uniq

Array.prototype.uniq = function(){
    for (var i=0,l=this.length; i<l; i++) {
        if (this.indexOf(this[i]) < i) {
            this.splice(i--, l-- && 1);
        }
    }
    return this;
};
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9].uniq()
// -> [3, 1, 4, 5, 9, 2, 6, 8, 7]

アレイのuniq JavaScriptで どう書く?org

アレイのuniqどう書く?org - 口から出まかせ

もう同じアプローチの解法は出てるんだけど、lengthを変数に取っておくとちょっと効率化できる。

あと、問答無用で破壊するのがJavaScript流だと思うので、そうした。

潰したくないときは、ary.concat().uniq()のように事前に複製する。


Core JavaScript 1.5 Reference:Global Objects:Array:indexOf - MDC

Array#indexOfは普通に===演算子でチェックする。

ハッシュを使ってのfor...in構文だと要素がオブジェクトのときとか困るし、意外と悪くないアプローチに思える。

問題はArray#indexOfが1.6の新機能なのと、[1,2] === [1,2]がfalseになるあたり……

unevalでmap、uniq、evalでmapとかかなあ。

[1, "2", {a: 3}, [4, 5], 1, "2", {a: 3}, [4, 5], 6].uniq()
// -> [1, "2", Object a=3, [4, 5], Object a=3, [4, 5], 6]

[1, "2", {a: 3}, [4, 5], 1, "2", {a: 3}, [4, 5], 6].map(uneval).uniq().map(eval)
// -> [1, "2", Object a=3, [4, 5], 6]
//    非破壊

追記

Array#indexOfだと最後まで走査してしまって無駄が多いので、ちょっと効率化。

Array.prototype.uniq = function(){
    for (var i=0,l=this.length; i<l; i++) {
        for (var j=0; j<i; j++) {
            if (this[i] === this[j]) {
                this.splice(i--, l-- && 1);
            }
        }
    }
    return this;
};

JavaScript: nise Array Comprehensions

var acomp = function(str){
    var m = str.match(/^(.+)\s+for\s+each\s+\((\w+)\s+in\s+range\((\d+),\s*(\d+)\)\)(\s+if\s+.*)?$/);
    if (!m) return [];
    var o = { expr: m[1], i: m[2], begin: m[3], end: m[4], ifcond: m[5] };
    var code = "var ary=[]; for (var ${i}=${begin}; ${i}<${end}; ${i}++) { ${ifcond} ary.push(${expr}); } return ary;".replace(/\$\{(\w+)\}/g, function($0,$1){
        return typeof(o[$1]) !== "undefined" ? o[$1] : "";
    });
    return (new Function(code))();
};
ten_squares = acomp("i * i for each (i in range(0, 10))");
// -> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
evens = acomp("i for each (i in range(0, 21)) if (i % 2 == 0)");
// -> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

for each rangeしか使えないわ、ジェネレータでもなんでもないわで、もう、ぜんぜんダメダメ。

CSS: overflow:hidden;とwidth指定でclearfix

クロスブラウザのためのHTML/CSSのテクニック集 | コリス

div#container {
    overflow: hidden;
    width: 100%; /* for IE hasLayout */
}

div#main {
    float: left;
    width: 70%;
}

dl#menu {
    float: right;
    width: 30%;
}

コンテナをoverflow: hidden;にすると計算方法が変わって、offsetHeightもまともな値になるみたい。

CSSはバッドノウハウの総合商社ですね。