/* destructively finds the intersection of* two arrays in a simple fashion.** PARAMS* a - first array, must already be sorted* b - second array, must already be sorted** NOTES* State of input arrays is undefined when* the function returns. They should be* (prolly) be dumped.** Should have O(n) operations, where n is* n = MIN(a.length, b.length)*/function intersection_destructive(a, b){var result = [];while( a.length > 0 && b.length > 0 ){if (a[0] < b[0] ){ a.shift(); }else if (a[0] > b[0] ){ b.shift(); }else /* they're equal */{result.push(a.shift());b.shift();}}
return result;}
非破坏性必须更复杂,因为我们必须跟踪索引:
/* finds the intersection of* two arrays in a simple fashion.** PARAMS* a - first array, must already be sorted* b - second array, must already be sorted** NOTES** Should have O(n) operations, where n is* n = MIN(a.length(), b.length())*/function intersect_safe(a, b){var ai=0, bi=0;var result = [];
while( ai < a.length && bi < b.length ){if (a[ai] < b[bi] ){ ai++; }else if (a[ai] > b[bi] ){ bi++; }else /* they're equal */{result.push(a[ai]);ai++;bi++;}}
return result;}
Array.prototype.contains = function(elem) {return(this.indexOf(elem) > -1);};
Array.prototype.intersect = function( array ) {// this is naive--could use some optimizationvar result = [];for ( var i = 0; i < this.length; i++ ) {if ( array.contains(this[i]) && !result.contains(this[i]) )result.push( this[i] );}return result;}
getIntersection: (arrays) ->if not arrays.lengthreturn []a1 = arrays[0]for a2 in arrays.slice(1)a = (val for val in a1 when val in a2)a1 = areturn a1.unique()
if (!Array.prototype.intersect){Array.prototype.intersect = function (arr1) {
var r = [], o = {}, l = this.length, i, v;for (i = 0; i < l; i++) {o[this[i]] = true;}l = arr1.length;for (i = 0; i < l; i++) {v = arr1[i];if (v in o) {r.push(v);}}return r;};}
// process array [element, element...], if allow abort ignore the resultfunction processArray(arr_a, cb_a, blnAllowAbort_a){var arrResult = [];var blnAborted = false;var intI = 0;
while ((intI < arr_a.length) && (blnAborted === false)){if (blnAllowAbort_a){blnAborted = cb_a(arr_a[intI]);}else{arrResult[intI] = cb_a(arr_a[intI]);}intI++;}
return arrResult;}
// process array of operations [operation,arguments...]function processOperations(arrOperations_a){var arrResult = [];var fnOperationE;
for(var intI = 0, intR = 0; intI < arrOperations_a.length; intI+=2, intR++){var fnOperation = arrOperations_a[intI+0];var fnArgs = arrOperations_a[intI+1];if (fnArgs === undefined){arrResult[intR] = fnOperation();}else{arrResult[intR] = fnOperation(fnArgs);}}
return arrResult;}
// return whether an element exists in an arrayfunction find(arr_a, varElement_a){var blnResult = false;
processArray(arr_a, function(varToMatch_a){var blnAbort = false;
if (varToMatch_a === varElement_a){blnResult = true;blnAbort = true;}
return blnAbort;}, true);
return blnResult;}
// return the union of all setsfunction union(arr_a){var arrResult = [];var intI = 0;
processArray(arr_a, function(arrSet_a){processArray(arrSet_a, function(varElement_a){// if the element doesn't exist in our resultif (find(arrResult, varElement_a) === false){// add itarrResult[intI] = varElement_a;intI++;}});});
return arrResult;}
// return the intersection of all setsfunction intersection(arr_a){var arrResult = [];var intI = 0;
// for each setprocessArray(arr_a, function(arrSet_a){// every number is a candidateprocessArray(arrSet_a, function(varCandidate_a){var blnCandidate = true;
// for each setprocessArray(arr_a, function(arrSet_a){// check that the candidate existsvar blnFoundPart = find(arrSet_a, varCandidate_a);
// if the candidate does not existif (blnFoundPart === false){// no longer a candidateblnCandidate = false;}});
if (blnCandidate){// if the candidate doesn't exist in our resultif (find(arrResult, varCandidate_a) === false){// add itarrResult[intI] = varCandidate_a;intI++;}}});});
return arrResult;}
var strOutput = ''
var arrSet1 = [1,2,3];var arrSet2 = [2,5,6];var arrSet3 = [7,8,9,2];
// return the union of the setsstrOutput = union([arrSet1, arrSet2, arrSet3]);alert(strOutput);
// return the intersection of 3 setsstrOutput = intersection([arrSet1, arrSet2, arrSet3]);alert(strOutput);
// of 3 sets of sets, which set is the intersecting setstrOutput = processOperations([intersection,[[arrSet1, arrSet2], [arrSet2], [arrSet2, arrSet3]]]);alert(strOutput);
function intersect(a, b) {var setA = new Set(a);var setB = new Set(b);var intersection = new Set([...setA].filter(x => setB.has(x)));return Array.from(intersection);}
更短,但可读性较差(也没有创建额外的交集Set):
function intersect(a, b) {var setB = new Set(b);return [...new Set(a)].filter(x => setB.has(x));}
// Return elements of array a that are also in b in linear time:function intersect(a, b) {return a.filter(Set.prototype.has, new Set(b));}
// Example:console.log(intersect([1,2,3], [2,3,4,5]));
function intersect_for(a, b) {const result = [];const alen = a.length;const blen = b.length;for (let i = 0; i < alen; ++i) {const ai = a[i];for (let j = 0; j < blen; ++j) {if (ai === b[j]) {result.push(ai);break;}}}return result;}
function intersect_filter_indexOf(a, b) {return a.filter(el => b.indexOf(el) !== -1);}
function intersect_filter_in(a, b) {const map = b.reduce((map, el) => {map[el] = true; return map}, {});return a.filter(el => el in map);}
function intersect_for_in(a, b) {const result = [];const map = {};for (let i = 0, length = b.length; i < length; ++i) {map[b[i]] = true;}for (let i = 0, length = a.length; i < length; ++i) {if (a[i] in map) result.push(a[i]);}return result;}
function intersect_filter_includes(a, b) {return a.filter(el => b.includes(el));}
function intersect_filter_has_this(a, b) {return a.filter(Set.prototype.has, new Set(b));}
function intersect_filter_has_arrow(a, b) {const set = new Set(b);return a.filter(el => set.has(el));}
function intersect_for_has(a, b) {const result = [];const set = new Set(b);for (let i = 0, length = a.length; i < length; ++i) {if (set.has(a[i])) result.push(a[i]);}return result;}
Firefox 53的结果:
大数组(10,000个元素)上的Ops/sec:
filter + has (this) 523 (this answer)for + has 482for-loop + in 279filter + in 242for-loops 24filter + includes 14filter + indexOf 10
Ops/sec on small arrays (100 elements):
for-loop + in 384,426filter + in 192,066for-loops 159,137filter + includes 104,068filter + indexOf 71,598filter + has (this) 43,531 (this answer)filter + has (arrow function) 35,588
function array_intersect(array1, array2){var mergedElems = {},result = [],firstArray, secondArray,firstN = 0,secondN = 0;
function generateStrKey(elem) {var typeOfElem = typeof elem;if (typeOfElem === 'object') {typeOfElem += Object.prototype.toString.call(elem);}return [typeOfElem, elem.toString(), JSON.stringify(elem)].join('__');}
// Executes the loops only if both arrays have valuesif (array1.length && array2.length){// Begins with the shortest array to optimize the algorithmif (array1.length < array2.length) {firstArray = array1;secondArray = array2;} else {firstArray = array2;secondArray = array1;}
firstArray.forEach(function(elem) {var key = generateStrKey(elem);if (!(key in mergedElems)) {mergedElems[key] = {elem: elem, inArray2: false};// Increases the counter of unique values in the first arrayfirstN++;}});
secondArray.some(function(elem) {var key = generateStrKey(elem);if (key in mergedElems) {if (!mergedElems[key].inArray2) {mergedElems[key].inArray2 = true;// Increases the counter of matchessecondN++;// If all elements of first array have coincidence, then exits the loopreturn (secondN === firstN);}}});
Object.values(mergedElems).forEach(function(elem) {if (elem.inArray2) {result.push(elem.elem);}});}
return result;}