Kết hợp ý tưởng từ Christoph và giả sử một vài phương pháp lặp không chuẩn trên mảng và đối tượng / hàm băm ( each
và bạn bè), chúng ta có thể nhận được sự khác biệt được đặt, sự kết hợp và giao điểm theo thời gian tuyến tính trong tổng số khoảng 20 dòng:
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);
}
};
Điều này giả định rằng each
và filter
được định nghĩa cho các mảng và chúng ta có hai phương thức tiện ích:
myUtils.keys(hash)
: trả về một mảng với các khóa của hàm băm
myUtils.select(hash, fnSelector,
fnEvaluator)
: trả về một mảng với kết quả của việc gọi fnEvaluator
các cặp khóa / giá trị mà
fnSelector
trả về true.
Nó select()
được lấy cảm hứng từ Common Lisp, và chỉ đơn thuần filter()
và map()
được cuộn thành một. (Sẽ tốt hơn nếu chúng được xác định trên đó Object.prototype
, nhưng làm như vậy sẽ phá hủy jQuery, vì vậy tôi đã giải quyết cho các phương thức tiện ích tĩnh.)
Hiệu suất: Thử nghiệm với
var a = [], b = [];
for (var i = 100000; i--; ) {
if (i % 2 !== 0) a.push(i);
if (i % 3 !== 0) b.push(i);
}
cho hai bộ với 50.000 và 66.666 phần tử. Với những giá trị này, AB mất khoảng 75ms, trong khi liên hiệp và giao điểm mỗi đoạn khoảng 150ms. (Mac Safari 4.0, sử dụng Javascript Date để tính thời gian.)
Tôi nghĩ đó là phần thưởng xứng đáng cho 20 dòng mã.