ทั้งหมดการแก้ปัญหาดังกล่าวข้างต้น "งาน" แต่น้อยกว่าที่ดีที่สุดสำหรับการทำงานและวิธีการทุกปัญหาในลักษณะเดียวกันซึ่งเป็นเส้นตรงค้นหารายการทั้งหมดในแต่ละจุดใช้Array.prototype.indexOfหรือArray.prototype.includes วิธีแก้ปัญหาที่เร็วกว่ามาก (เร็วกว่าการค้นหาแบบไบนารีในกรณีส่วนใหญ่) คือการจัดเรียงอาร์เรย์และข้ามไปข้างหน้าตามที่แสดงด้านล่าง อย่างไรก็ตามข้อเสียอย่างหนึ่งคือสิ่งนี้ต้องการให้รายการทั้งหมดในอาร์เรย์เป็นตัวเลขหรือสตริง อย่างไรก็ตามในบางกรณีการค้นหาแบบไบนารีอาจเร็วกว่าการค้นหาเชิงเส้นแบบก้าวหน้า กรณีเหล่านี้เกิดขึ้นจากการที่การค้นหาเชิงเส้นแบบก้าวหน้าของฉันมีความซับซ้อนของO (2n 1 + n 2 ) (เฉพาะO (n 1+ n 2 ) n 2คืออาร์เรย์ตัวกรอง) ในขณะที่การค้นหาแบบไบนารีมีความซับซ้อนของO (n 1 ceil (log 2 n 2 )) ( ceil = ปัดเศษขึ้น - ไปที่เพดานใน ) และสุดท้ายดัชนีของการค้นหามีความซับซ้อนที่ผันแปรได้สูงระหว่างO (n 1 )และO (n 1 n 2 )โดยเฉลี่ยออกเป็นO (n 1 ceil (n 2) ÷ 2)) . ดังนั้น indexOf จะเร็วที่สุดโดยเฉลี่ยในกรณีของในเวอร์ชัน C / C ++ ที่เร็วกว่า) (โดยที่n 1คืออาร์เรย์ที่ค้นหาและ(n 1 , n 2 )เท่ากับ{1,2} , {1,3}หรือ{x 1 | x∈N} อย่างไรก็ตามนี่ยังไม่ใช่การนำเสนอฮาร์ดแวร์สมัยใหม่ที่สมบูรณ์แบบ IndexOf มีการเพิ่มประสิทธิภาพในการกำเนิดเท่าที่ขอบเขตในเบราว์เซอร์ที่ทันสมัยที่สุดทำให้มันมากภายใต้กฎหมายของการทำนายสาขา ดังนั้นหากเราตั้งสมมติฐานเดียวกันกับ indexOf เหมือนกับที่เราทำกับการค้นหาเชิงเส้นและไบนารีแบบโปรเกรสซีฟนั่นคืออาร์เรย์ถูกกำหนดไว้ล่วงหน้าแล้วตามสถิติที่ระบุไว้ในลิงก์เราสามารถคาดหวังว่า IndexOf จะเร็วขึ้น 6 เท่า เปลี่ยนความซับซ้อนไประหว่างO (n 1 ÷ 6)และO (n 1 n 2 )ค่าเฉลี่ยออกไปO (n 1 ceil (n 2 7 ÷ . สุดท้ายโปรดทราบว่าโซลูชันด้านล่างนี้จะไม่ทำงานกับอ็อบเจ็กต์เนื่องจากอ็อบเจ็กต์ใน JavaScript ไม่สามารถเปรียบเทียบด้วยพอยน์เตอร์ใน JavaScript
function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
var out=[], value=0;
for (var i=0, len=array.length|0; i < len; i=i+1|0)
if (handle(value = array[i]))
out.push( value );
return out;
}
const Math_clz32 = Math.clz32 || (function(log, LN2){
return function(x) {
return 31 - log(x >>> 0) / LN2 | 0;
};
})(Math.log, Math.LN2);
function filterArrayByAnotherArray(searchArray, filterArray) {
if (
typeof searchArray[0] == "number" &&
typeof filterArray[0] == "number" &&
(searchArray[0]|0) === searchArray[0] &&
(filterArray[0]|0) === filterArray[0]
) {filterArray
searchArray.sort(sortIntArray);
filterArray.sort(sortIntArray);
} else {
searchArray.sort(sortAnyArray);
filterArray.sort(sortAnyArray);
}
var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
var progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
var i = 0;
if (progressiveLinearComplexity < binarySearchComplexity) {
return fastFilter(searchArray, function(currentValue){
while (filterArray[i] < currentValue) i=i+1|0;
return filterArray[i] !== currentValue;
});
} else {
return fastFilter(
searchArray,
fastestBinarySearch(filterArray)
);
}
}
function fastestBinarySearch(array){
var initLen = (array.length|0) - 1 |0;
const compGoto = Math_clz32(initLen) & 31;
return function(sValue) {
var len = initLen |0;
switch (compGoto) {
case 0:
if (len & 0x80000000) {
const nCB = len & 0x80000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 1:
if (len & 0x40000000) {
const nCB = len & 0xc0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 2:
if (len & 0x20000000) {
const nCB = len & 0xe0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 3:
if (len & 0x10000000) {
const nCB = len & 0xf0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 4:
if (len & 0x8000000) {
const nCB = len & 0xf8000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 5:
if (len & 0x4000000) {
const nCB = len & 0xfc000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 6:
if (len & 0x2000000) {
const nCB = len & 0xfe000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 7:
if (len & 0x1000000) {
const nCB = len & 0xff000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 8:
if (len & 0x800000) {
const nCB = len & 0xff800000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 9:
if (len & 0x400000) {
const nCB = len & 0xffc00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 10:
if (len & 0x200000) {
const nCB = len & 0xffe00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 11:
if (len & 0x100000) {
const nCB = len & 0xfff00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 12:
if (len & 0x80000) {
const nCB = len & 0xfff80000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 13:
if (len & 0x40000) {
const nCB = len & 0xfffc0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 14:
if (len & 0x20000) {
const nCB = len & 0xfffe0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 15:
if (len & 0x10000) {
const nCB = len & 0xffff0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 16:
if (len & 0x8000) {
const nCB = len & 0xffff8000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 17:
if (len & 0x4000) {
const nCB = len & 0xffffc000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 18:
if (len & 0x2000) {
const nCB = len & 0xffffe000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 19:
if (len & 0x1000) {
const nCB = len & 0xfffff000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 20:
if (len & 0x800) {
const nCB = len & 0xfffff800;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 21:
if (len & 0x400) {
const nCB = len & 0xfffffc00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 22:
if (len & 0x200) {
const nCB = len & 0xfffffe00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 23:
if (len & 0x100) {
const nCB = len & 0xffffff00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 24:
if (len & 0x80) {
const nCB = len & 0xffffff80;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 25:
if (len & 0x40) {
const nCB = len & 0xffffffc0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 26:
if (len & 0x20) {
const nCB = len & 0xffffffe0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 27:
if (len & 0x10) {
const nCB = len & 0xfffffff0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 28:
if (len & 0x8) {
const nCB = len & 0xfffffff8;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 29:
if (len & 0x4) {
const nCB = len & 0xfffffffc;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 30:
if (len & 0x2) {
const nCB = len & 0xfffffffe;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 31:
if (len & 0x1) {
const nCB = len & 0xffffffff;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
}
if (array[len|0] !== sValue) {
return true;
} else {
return false;
}
};
}
โปรดดูโพสต์อื่น ๆ ของฉันที่นี่สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับอัลกอริทึมการค้นหาแบบไบนารีที่ใช้
หากคุณรู้สึกแย่เกี่ยวกับขนาดไฟล์ (ซึ่งฉันเคารพ) คุณสามารถเสียสละประสิทธิภาพเพียงเล็กน้อยเพื่อลดขนาดไฟล์ลงอย่างมากและเพิ่มความสามารถในการบำรุงรักษา
function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
var out=[], value=0;
for (var i=0, len=array.length|0; i < len; i=i+1|0)
if (handle(value = array[i]))
out.push( value );
return out;
}
function filterArrayByAnotherArray(searchArray, filterArray) {
if (
typeof searchArray[0] == "number" &&
typeof filterArray[0] == "number" &&
(searchArray[0]|0) === searchArray[0] &&
(filterArray[0]|0) === filterArray[0]
) {
searchArray.sort(sortIntArray);
filterArray.sort(sortIntArray);
} else {
searchArray.sort(sortAnyArray);
filterArray.sort(sortAnyArray);
}
var i = 0;
return fastFilter(searchArray, function(currentValue){
while (filterArray[i] < currentValue) i=i+1|0;
return filterArray[i] !== currentValue;
});
}
เพื่อพิสูจน์ความแตกต่างของความเร็วให้เราตรวจสอบ JSPerfs สำหรับการกรองอาร์เรย์ 16 องค์ประกอบการค้นหาแบบไบนารีจะเร็วกว่า indexOf ประมาณ 17% ในขณะที่ filterArrayByAnotherArray เร็วกว่า indexOf ประมาณ 93% สำหรับการกรองอาร์เรย์ของ 256 องค์ประกอบการค้นหาไบนารีจะเร็วกว่า indexOf ประมาณ 291% ในขณะที่ filterArrayByAnotherArray เร็วกว่า indexOf ประมาณ 353% สำหรับการกรองอาร์เรย์ขององค์ประกอบ 4096ค้นหาไบนารีจะเร็วกว่า indexOf ประมาณ 2655% ในขณะที่ filterArrayByAnotherArray เร็วกว่า indexOf ประมาณ 4627%
การกรองย้อนกลับ (เช่นประตู AND)
ส่วนก่อนหน้านี้ระบุรหัสเพื่อรับอาร์เรย์ A และอาร์เรย์ B และลบองค์ประกอบทั้งหมดจาก A ที่มีอยู่ใน B:
filterArrayByAnotherArray(
[1,3,5],
[2,3,4]
);
ส่วนถัดไปนี้จะให้รหัสสำหรับการกรองย้อนกลับโดยที่เราจะลบองค์ประกอบทั้งหมดออกจาก A ที่ไม่มีอยู่ใน B กระบวนการนี้เทียบเท่ากับการรักษาเฉพาะองค์ประกอบทั่วไปของทั้ง A และ B เช่นประตู AND:
reverseFilterArrayByAnotherArray(
[1,3,5],
[2,3,4]
);
นี่คือรหัสสำหรับการกรองย้อนกลับ:
function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
var out=[], value=0;
for (var i=0, len=array.length|0; i < len; i=i+1|0)
if (handle(value = array[i]))
out.push( value );
return out;
}
const Math_clz32 = Math.clz32 || (function(log, LN2){
return function(x) {
return 31 - log(x >>> 0) / LN2 | 0;
};
})(Math.log, Math.LN2);
function reverseFilterArrayByAnotherArray(searchArray, filterArray) {
if (
typeof searchArray[0] == "number" &&
typeof filterArray[0] == "number" &&
(searchArray[0]|0) === searchArray[0] &&
(filterArray[0]|0) === filterArray[0]
) {
searchArray.sort(sortIntArray);
filterArray.sort(sortIntArray);
} else {
searchArray.sort(sortAnyArray);
filterArray.sort(sortAnyArray);
}
var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
var progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
var i = 0;
if (progressiveLinearComplexity < binarySearchComplexity) {
return fastFilter(searchArray, function(currentValue){
while (filterArray[i] < currentValue) i=i+1|0;
return filterArray[i] === currentValue;
});
} else {
return fastFilter(
searchArray,
inverseFastestBinarySearch(filterArray)
);
}
}
function inverseFastestBinarySearch(array){
var initLen = (array.length|0) - 1 |0;
const compGoto = Math_clz32(initLen) & 31;
return function(sValue) {
var len = initLen |0;
switch (compGoto) {
case 0:
if (len & 0x80000000) {
const nCB = len & 0x80000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 1:
if (len & 0x40000000) {
const nCB = len & 0xc0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 2:
if (len & 0x20000000) {
const nCB = len & 0xe0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 3:
if (len & 0x10000000) {
const nCB = len & 0xf0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 4:
if (len & 0x8000000) {
const nCB = len & 0xf8000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 5:
if (len & 0x4000000) {
const nCB = len & 0xfc000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 6:
if (len & 0x2000000) {
const nCB = len & 0xfe000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 7:
if (len & 0x1000000) {
const nCB = len & 0xff000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 8:
if (len & 0x800000) {
const nCB = len & 0xff800000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 9:
if (len & 0x400000) {
const nCB = len & 0xffc00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 10:
if (len & 0x200000) {
const nCB = len & 0xffe00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 11:
if (len & 0x100000) {
const nCB = len & 0xfff00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 12:
if (len & 0x80000) {
const nCB = len & 0xfff80000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 13:
if (len & 0x40000) {
const nCB = len & 0xfffc0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 14:
if (len & 0x20000) {
const nCB = len & 0xfffe0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 15:
if (len & 0x10000) {
const nCB = len & 0xffff0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 16:
if (len & 0x8000) {
const nCB = len & 0xffff8000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 17:
if (len & 0x4000) {
const nCB = len & 0xffffc000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 18:
if (len & 0x2000) {
const nCB = len & 0xffffe000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 19:
if (len & 0x1000) {
const nCB = len & 0xfffff000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 20:
if (len & 0x800) {
const nCB = len & 0xfffff800;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 21:
if (len & 0x400) {
const nCB = len & 0xfffffc00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 22:
if (len & 0x200) {
const nCB = len & 0xfffffe00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 23:
if (len & 0x100) {
const nCB = len & 0xffffff00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 24:
if (len & 0x80) {
const nCB = len & 0xffffff80;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 25:
if (len & 0x40) {
const nCB = len & 0xffffffc0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 26:
if (len & 0x20) {
const nCB = len & 0xffffffe0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 27:
if (len & 0x10) {
const nCB = len & 0xfffffff0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 28:
if (len & 0x8) {
const nCB = len & 0xfffffff8;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 29:
if (len & 0x4) {
const nCB = len & 0xfffffffc;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 30:
if (len & 0x2) {
const nCB = len & 0xfffffffe;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 31:
if (len & 0x1) {
const nCB = len & 0xffffffff;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
}
if (array[len|0] !== sValue) {
return false;
} else {
return true;
}
};
}
สำหรับโค้ดการกรองย้อนกลับรุ่นเล็กที่ช้ากว่าโปรดดูด้านล่าง
function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
var out=[], value=0;
for (var i=0, len=array.length|0; i < len; i=i+1|0)
if (handle(value = array[i]))
out.push( value );
return out;
}
function reverseFilterArrayByAnotherArray(searchArray, filterArray) {
if (
typeof searchArray[0] == "number" &&
typeof filterArray[0] == "number" &&
(searchArray[0]|0) === searchArray[0] &&
(filterArray[0]|0) === filterArray[0]
) {
searchArray.sort(sortIntArray);
filterArray.sort(sortIntArray);
} else {
searchArray.sort(sortAnyArray);
filterArray.sort(sortAnyArray);
}
var i = 0;
return fastFilter(searchArray, function(currentValue){
while (filterArray[i] < currentValue) i=i+1|0;
return filterArray[i] === currentValue;
});
}
return arrTwo.indexOf(e) === -1;
รหัส:var filteredArr = firstArr.filter(el => secondArr.indexOf(el) === -1);