Uwzględniając pomysł Christopha i zakładając kilka niestandardowych metod iteracji na tablicach i obiektach / hashach ( each
i przyjaciołach), możemy uzyskać różnicę, sumę i przecięcie w czasie liniowym w sumie w około 20 liniach:
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);
}
};
Zakłada się, że each
i filter
są zdefiniowane dla tablic oraz że mamy dwie metody narzędziowe:
myUtils.keys(hash)
: zwraca tablicę z kluczami z skrótu
myUtils.select(hash, fnSelector,
fnEvaluator)
: zwraca tablicę z wynikami wywołania fnEvaluator
par klucz / wartość, dla których
fnSelector
zwraca prawdę.
select()
Jest luźno inspirowany Common Lisp, a jest jedynie filter()
i map()
w jednym. (Lepiej byłoby mieć je zdefiniowaneObject.prototype
, ale zrobienie tego wraki spustoszenie w jQuery, więc zdecydowałem się na statyczne metody narzędziowe).
Wydajność: testowanie w
var a = [], b = [];
for (var i = 100000; i--; ) {
if (i % 2 !== 0) a.push(i);
if (i % 3 !== 0) b.push(i);
}
daje dwa zestawy po 50 000 i 66 666 elementów. Przy tych wartościach AB trwa około 75 ms, podczas gdy suma i przecięcie trwają około 150 ms. (Mac Safari 4.0, synchronizacja z wykorzystaniem daty JavaScript).
Myślę, że to przyzwoita zapłata za 20 linii kodu.