Wenn each
wir die Idee von Christoph einbeziehen und einige nicht standardmäßige Iterationsmethoden für Arrays und Objekte / Hashes ( und Freunde) annehmen , können wir Differenz, Vereinigung und Schnittmenge in linearer Zeit in insgesamt etwa 20 Zeilen festlegen:
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);
}
};
Dies setzt voraus, dass each
und filter
für Arrays definiert sind und dass wir zwei Dienstprogrammmethoden haben:
myUtils.keys(hash)
: Gibt ein Array mit den Schlüsseln des Hash zurück
myUtils.select(hash, fnSelector,
fnEvaluator)
: Gibt ein Array mit den Ergebnissen des Aufrufs fnEvaluator
der Schlüssel / Wert-Paare zurück, für die
fnSelector
true zurückgegeben wird.
Das select()
ist lose von Common Lisp inspiriert und ist nur filter()
und map()
in einem gerollt. (Es wäre besser, sie definiert zu habenObject.prototype
, aber dies führt zu einem Chaos mit jQuery, sodass ich mich für statische Dienstprogrammmethoden entschieden habe.)
Leistung: Testen mit
var a = [], b = [];
for (var i = 100000; i--; ) {
if (i % 2 !== 0) a.push(i);
if (i % 3 !== 0) b.push(i);
}
gibt zwei Sätze mit 50.000 und 66.666 Elementen. Mit diesen Werten dauert AB ungefähr 75 ms, während Vereinigung und Schnittpunkt jeweils ungefähr 150 ms betragen. (Mac Safari 4.0 mit Javascript-Datum für das Timing.)
Ich denke, das ist eine anständige Auszahlung für 20 Codezeilen.