用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
当前回答
我扩展了tarulen的答案,以适用于任何数量的数组。它也应该适用于非整数值。
function intersect() {
const last = arguments.length - 1;
var seen={};
var result=[];
for (var i = 0; i < last; i++) {
for (var j = 0; j < arguments[i].length; j++) {
if (seen[arguments[i][j]]) {
seen[arguments[i][j]] += 1;
}
else if (!i) {
seen[arguments[i][j]] = 1;
}
}
}
for (var i = 0; i < arguments[last].length; i++) {
if ( seen[arguments[last][i]] === last)
result.push(arguments[last][i]);
}
return result;
}
其他回答
我在ES6方面的贡献。一般来说,它会找到一个数组与作为参数提供的不确定数量的数组的交集。
Array.prototype.intersect = function(…a) { 返回(这个,…).reduce ((p c) = > p.filter (e = > c.includes (e))); } Var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]], Arr = [0,1,2,3,4,5,6,7,8,9]; 文档。以前写(“< >”+ JSON.stringify (arr.intersect (arr)) + " < / pre > ");
这是一个提议的标准:对于当前阶段2的提议https://github.com/tc39/proposal-set-methods,您可以使用
mySet.intersection(mySet2);
在此之前,你可以使用Immutable.js的Set,它激发了这个提议
Immutable.Set(mySet).intersect(mySet2)
ES2015的函数式方法
函数式方法必须考虑只使用没有副作用的纯函数,每个函数只与单个作业有关。
这些限制增强了所涉及函数的可组合性和可重用性。
//小的,可重用的辅助函数 const createSet = xs => new Set(xs); Const filter = f => xs => xs.filter(apply(f)); Const apply = f => x => f(x); / /十字路口 Const相交= xs => ys => { const zs =创建集(ys); 返回过滤器(x => zs.has(x)) ? 真正的 :假 ) (x); }; //模拟数据 Const xs = [1,2,2,3,4,5]; Const ys = [0,1,2,3,3,3,6,7,8,9]; //运行 Console.log (intersect(xs) (ys));
请注意,使用本机Set类型,这有一个优点 查找性能。
避免重复
显然,第一个数组中重复出现的项将被保留,而第二个数组将被去重。这可能是也可能不是理想的行为。如果你需要一个唯一的结果,只需对第一个参数应用重复数据删除:
// auxiliary functions const apply = f => x => f(x); const comp = f => g => x => f(g(x)); const afrom = apply(Array.from); const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); // intersection const intersect = xs => ys => { const zs = createSet(ys); return filter(x => zs.has(x) ? true : false ) (xs); }; // de-duplication const dedupe = comp(afrom) (createSet); // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,3,6,7,8,9]; // unique result console.log( intersect(dedupe(xs)) (ys) );
计算任意数量数组的交集
如果你想计算任意数量的数组的交点,只需用compose intersect和foldl。这是一个方便函数:
// auxiliary functions const apply = f => x => f(x); const uncurry = f => (x, y) => f(x) (y); const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); // intersection const intersect = xs => ys => { const zs = createSet(ys); return filter(x => zs.has(x) ? true : false ) (xs); }; // intersection of an arbitrarily number of Arrays const intersectn = (head, ...tail) => foldl(intersect) (head) (tail); // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,3,6,7,8,9]; const zs = [0,1,2,3,4,5,6]; // run console.log( intersectn(xs, ys, zs) );
使用Array.prototype.filter和Array.prototype.includes的组合:
const filteredArray = array1.filter(value => array2.includes(value));
对于较旧的浏览器,使用Array.prototype.indexOf且不使用箭头函数:
var filteredArray = array1.filter(function(n) {
return array2.indexOf(n) !== -1;
});
NB !.includes和. indexof都在内部使用===来比较数组中的元素,所以如果数组包含对象,它只比较对象引用(而不是对象的内容)。如果你想指定自己的比较逻辑,请使用Array.prototype.some。
我扩展了tarulen的答案,以适用于任何数量的数组。它也应该适用于非整数值。
function intersect() {
const last = arguments.length - 1;
var seen={};
var result=[];
for (var i = 0; i < last; i++) {
for (var j = 0; j < arguments[i].length; j++) {
if (seen[arguments[i][j]]) {
seen[arguments[i][j]] += 1;
}
else if (!i) {
seen[arguments[i][j]] = 1;
}
}
}
for (var i = 0; i < arguments[last].length; i++) {
if ( seen[arguments[last][i]] === last)
result.push(arguments[last][i]);
}
return result;
}