Christoph からのアイデアを取り入れ、配列とオブジェクト/ハッシュ (およびその仲間) に対していくつかの非標準の反復メソッドを想定するとeach
、合計約 20 行で集合差、結合、交差を線形時間で取得できます。
var setOPs = {
minusAB : function (a, b) {
var h = {};
b.each(function (v) { h[v] = true; });
return a.filter(function (v) { return !h.hasOwnProperty(v); });
},
unionAB : function (a, b) {
var h = {}, f = function (v) { h[v] = true; };
a.each(f);
b.each(f);
return myUtils.keys(h);
},
intersectAB : function (a, b) {
var h = {};
a.each(function (v) { h[v] = 1; });
b.each(function (v) { h[v] = (h[v] || 0) + 1; });
var fnSel = function (v, count) { return count > 1; };
var fnVal = function (v, c) { return v; };
return myUtils.select(h, fnSel, fnVal);
}
};
each
これは、とfilter
が配列に対して定義されていること、および 2 つのユーティリティ メソッドがあることを前提としています。
myUtils.keys(hash)
: ハッシュのキーを持つ配列を返します
myUtils.select(hash, fnSelector,
fnEvaluator)
fnEvaluator
: true を返すキーと値のペアを
呼び出した結果の配列をfnSelector
返します。
はselect()
Common Lisp から大まかに着想を得たもので、単純filter()
にmap()
1 つにまとめられています。(上で定義したほうがよいのですObject.prototype
が、そうすると jQuery が台無しになるので、静的なユーティリティ メソッドを使用することにしました。)
パフォーマンス: テスト
var a = [], b = [];
for (var i = 100000; i--; ) {
if (i % 2 !== 0) a.push(i);
if (i % 3 !== 0) b.push(i);
}
50,000 要素と 66,666 要素の 2 つのセットが得られます。これらの値では、AB は約 75 ミリ秒かかりますが、ユニオンと交差はそれぞれ約 150 ミリ秒かかります。(Mac Safari 4.0、タイミングに Javascript Date を使用)
これは、20 行のコードで十分な見返りだと思います。