用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
当前回答
function intersectionOfArrays(arr1, arr2) {
return arr1.filter((element) => arr2.indexOf(element) !== -1).filter((element, pos, self) => self.indexOf(element) == pos);
}
其他回答
另一种可以同时处理任意数量数组的索引方法:
// Calculate intersection of multiple array or object values.
function intersect (arrList) {
var arrLength = Object.keys(arrList).length;
// (Also accepts regular objects as input)
var index = {};
for (var i in arrList) {
for (var j in arrList[i]) {
var v = arrList[i][j];
if (index[v] === undefined) index[v] = 0;
index[v]++;
};
};
var retv = [];
for (var i in index) {
if (index[i] == arrLength) retv.push(i);
};
return retv;
};
它只适用于可以作为字符串计算的值,你应该将它们作为一个数组传递:
intersect ([arr1, arr2, arr3...]);
...但它透明地接受对象作为参数或任何要交叉的元素(总是返回公共值的数组)。例子:
intersect ({foo: [1, 2, 3, 4], bar: {a: 2, j:4}}); // [2, 4]
intersect ([{x: "hello", y: "world"}, ["hello", "user"]]); // ["hello"]
编辑:我只是注意到,这是,在某种程度上,有点bug。
也就是说:我在编码时认为输入数组本身不能包含重复(正如所提供的示例那样)。
但如果输入数组恰好包含重复,就会产生错误的结果。示例(使用下面的实现):
intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]
幸运的是,这很容易通过添加二级索引来解决。那就是:
变化:
if (index[v] === undefined) index[v] = 0;
index[v]++;
by:
if (index[v] === undefined) index[v] = {};
index[v][i] = true; // Mark as present in i input.
,:
if (index[i] == arrLength) retv.push(i);
by:
if (Object.keys(index[i]).length == arrLength) retv.push(i);
完整的例子:
// Calculate intersection of multiple array or object values.
function intersect (arrList) {
var arrLength = Object.keys(arrList).length;
// (Also accepts regular objects as input)
var index = {};
for (var i in arrList) {
for (var j in arrList[i]) {
var v = arrList[i][j];
if (index[v] === undefined) index[v] = {};
index[v][i] = true; // Mark as present in i input.
};
};
var retv = [];
for (var i in index) {
if (Object.keys(index[i]).length == arrLength) retv.push(i);
};
return retv;
};
intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]); // [ '1' ]
最简单、最快的O(n)和最短的方式:
函数交点(a, b) { const setA = new Set(a); 返回b.filter(value => setA.has(value)); } console.log(十字路口([1,2,3],[2、3、4、5)))
@nbarbosa几乎有相同的答案,但他将两个数组强制转换为Set,然后再转换回数组。不需要任何额外的选角。
基于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;
});
});
}
这是一个提议的标准:对于当前阶段2的提议https://github.com/tc39/proposal-set-methods,您可以使用
mySet.intersection(mySet2);
在此之前,你可以使用Immutable.js的Set,它激发了这个提议
Immutable.Set(mySet).intersect(mySet2)
我写了一个相交函数,它甚至可以根据对象的特定属性来检测对象数组的交集。
例如,
if arr1 = [{id: 10}, {id: 20}]
and arr2 = [{id: 20}, {id: 25}]
我们想要基于id属性的交集,那么输出应该是:
[{id: 20}]
因此,相同(注:ES6代码)的函数为:
const intersect = (arr1, arr2, accessors = [v => v, v => v]) => {
const [fn1, fn2] = accessors;
const set = new Set(arr2.map(v => fn2(v)));
return arr1.filter(value => set.has(fn1(value)));
};
你可以这样调用这个函数:
intersect(arr1, arr2, [elem => elem.id, elem => elem.id])
还要注意:该函数查找交集时考虑到第一个数组是主数组,因此交集结果将是主数组的结果。