เมื่อรวมแนวคิดจากคริสตอฟและสมมติว่ามีวิธีการทำซ้ำสองสามวิธีที่ไม่ได้มาตรฐานบนอาร์เรย์และอ็อบเจ็กต์ / แฮช ( 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
กำหนดไว้สำหรับอาร์เรย์และเรามีวิธียูทิลิตี้สองวิธี:
myUtils.keys(hash)
: ส่งคืนอาร์เรย์ด้วยคีย์ของแฮช
myUtils.select(hash, fnSelector,
fnEvaluator)
: ส่งคืนอาร์เรย์พร้อมผลลัพธ์ของการเรียกfnEvaluator
คู่คีย์ / ค่าซึ่ง
fnSelector
ส่งกลับค่าจริง
select()
เป็นแรงบันดาลใจอย่างอิสระโดยธรรมดาชัดและเป็นเพียงfilter()
และmap()
รีดเป็นหนึ่ง (จะดีกว่าถ้ากำหนดไว้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 ด้วยค่าเหล่านี้ AB จะใช้เวลาประมาณ 75ms ในขณะที่การรวมกันและจุดตัดจะอยู่ที่ประมาณ 150 มิลลิวินาที (Mac Safari 4.0 โดยใช้ Javascript Date เพื่อกำหนดเวลา)
ฉันคิดว่านั่นเป็นผลตอบแทนที่ดีสำหรับโค้ด 20 บรรทัด