用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
当前回答
使用Underscore.js或lodash.js
_.intersection( [0,345,324] , [1,0,324] ) // gives [0,324]
其他回答
如果你需要让它处理交叉多个数组:
Const intersect = (a1, a2,…rest) => { Const a12 = a1。过滤器(value => a2.includes(value)) 如果休息。长度=== 0){返回a12;} 回归相交(a12,…rest); }; console.log(相交([1、2、3、4、5],[1,2],[1、2、3、4、5],[2 10 1]))
基于Anon的出色回答,这个函数返回两个或多个数组的交集。
function arrayIntersect(arrayOfArrays)
{
var arrayCopy = arrayOfArrays.slice(),
baseArray = arrayCopy.pop();
return baseArray.filter(function(item) {
return arrayCopy.every(function(itemList) {
return itemList.indexOf(item) !== -1;
});
});
}
通过使用.pop而不是.shift可以提高@atk实现对原语排序数组的性能。
function intersect(array1, array2) {
var result = [];
// Don't destroy the original arrays
var a = array1.slice(0);
var b = array2.slice(0);
var aLast = a.length - 1;
var bLast = b.length - 1;
while (aLast >= 0 && bLast >= 0) {
if (a[aLast] > b[bLast] ) {
a.pop();
aLast--;
} else if (a[aLast] < b[bLast] ){
b.pop();
bLast--;
} else /* they're equal */ {
result.push(a.pop());
b.pop();
aLast--;
bLast--;
}
}
return result;
}
我使用jsPerf创建了一个基准测试。使用。pop要快三倍。
//在线性时间内返回数组a中也在b中的元素: 函数相交(a, b) { 返回a.filter (Set.prototype。new Set(b)); } / /例如: console.log(相交([1,2,3],[2、3、4、5]));
我推荐上述简洁的解决方案,它在大输入上优于其他实现。如果在小输入上的性能很重要,请检查下面的替代方案。
备选方案和性能比较:
有关替代实现,请参阅下面的代码片段,并检查https://jsperf.com/array-intersection-comparison以进行性能比较。
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的结果:
Ops/sec on large arrays (10,000 elements): filter + has (this) 523 (this answer) for + has 482 for-loop + in 279 filter + in 242 for-loops 24 filter + includes 14 filter + indexOf 10 Ops/sec on small arrays (100 elements): for-loop + in 384,426 filter + in 192,066 for-loops 159,137 filter + includes 104,068 filter + indexOf 71,598 filter + has (this) 43,531 (this answer) filter + has (arrow function) 35,588
与效率无关,但很容易理解,这里有一个集合的并和交的例子,它处理集合的数组和集合的集合。
http://jsfiddle.net/zhulien/NF68T/
// process array [element, element...], if allow abort ignore the result
function 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 array
function 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 sets
function 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 result
if (find(arrResult, varElement_a) === false)
{
// add it
arrResult[intI] = varElement_a;
intI++;
}
});
});
return arrResult;
}
// return the intersection of all sets
function intersection(arr_a)
{
var arrResult = [];
var intI = 0;
// for each set
processArray(arr_a, function(arrSet_a)
{
// every number is a candidate
processArray(arrSet_a, function(varCandidate_a)
{
var blnCandidate = true;
// for each set
processArray(arr_a, function(arrSet_a)
{
// check that the candidate exists
var blnFoundPart = find(arrSet_a, varCandidate_a);
// if the candidate does not exist
if (blnFoundPart === false)
{
// no longer a candidate
blnCandidate = false;
}
});
if (blnCandidate)
{
// if the candidate doesn't exist in our result
if (find(arrResult, varCandidate_a) === false)
{
// add it
arrResult[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 sets
strOutput = union([arrSet1, arrSet2, arrSet3]);
alert(strOutput);
// return the intersection of 3 sets
strOutput = intersection([arrSet1, arrSet2, arrSet3]);
alert(strOutput);
// of 3 sets of sets, which set is the intersecting set
strOutput = processOperations([intersection,[[arrSet1, arrSet2], [arrSet2], [arrSet2, arrSet3]]]);
alert(strOutput);