用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
当前回答
使用一个数组创建一个Object,并循环遍历第二个数组以检查该值是否作为key存在。
function intersection(arr1, arr2) {
var myObj = {};
var myArr = [];
for (var i = 0, len = arr1.length; i < len; i += 1) {
if(myObj[arr1[i]]) {
myObj[arr1[i]] += 1;
} else {
myObj[arr1[i]] = 1;
}
}
for (var j = 0, len = arr2.length; j < len; j += 1) {
if(myObj[arr2[j]] && myArr.indexOf(arr2[j]) === -1) {
myArr.push(arr2[j]);
}
}
return myArr;
}
其他回答
如果你需要让它处理交叉多个数组:
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]))
.reduce生成地图,.filter找到交叉路口。.filter中的Delete允许我们将第二个数组视为唯一的集合。
function intersection (a, b) {
var seen = a.reduce(function (h, k) {
h[k] = true;
return h;
}, {});
return b.filter(function (k) {
var exists = seen[k];
delete seen[k];
return exists;
});
}
我发现这种方法很容易解释。它在常数时间内运行。
//在线性时间内返回数组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
解决它 从索引0开始逐一检查,然后创建一个新数组。
像这样的东西,不过测试不太好。
function intersection(x,y){
x.sort();y.sort();
var i=j=0;ret=[];
while(i<x.length && j<y.length){
if(x[i]<y[j])i++;
else if(y[j]<x[i])j++;
else {
ret.push(x[i]);
i++,j++;
}
}
return ret;
}
alert(intersection([1,2,3], [2,3,4,5]));
PS:该算法仅适用于数字和普通字符串,任意对象数组的交集可能无法工作。
基于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;
});
});
}