用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
当前回答
对这里最小的一个(filter/indexOf解决方案)稍作调整,即使用JavaScript对象在其中一个数组中创建值的索引,将从O(N*M)减少到“可能”线性时间。source1 source2
function intersect(a, b) {
var aa = {};
a.forEach(function(v) { aa[v]=1; });
return b.filter(function(v) { return v in aa; });
}
这不是最简单的解决方案(它的代码比filter+indexOf要多),也不是最快的解决方案(可能比intersect_safe()慢一个常数因子),但似乎是一个很好的平衡。它非常简单,同时提供了良好的性能,并且不需要预先排序的输入。
其他回答
在coffescript中N个数组的交集
getIntersection: (arrays) ->
if not arrays.length
return []
a1 = arrays[0]
for a2 in arrays.slice(1)
a = (val for val in a1 when val in a2)
a1 = a
return a1.unique()
Var数组= [ [1,2,3], [2,3,4,5] ] 函数commonValue(…arr) { 令res = arr[0]。过滤(函数(x) { 返回arr.every((y) => y.includes(x)) }) 返回res; } commonValue数组(…);
这是一个现代和简单的ES6方式来做,也非常灵活。 它允许您指定多个数组作为与主题数组进行比较的数组,并且可以在包含和独占模式下工作。
// =======================================
// The function
// =======================================
function assoc(subjectArray, otherArrays, { mustBeInAll = true } = {}) {
return subjectArray.filter((subjectItem) => {
if (mustBeInAll) {
return otherArrays.every((otherArray) =>
otherArray.includes(subjectItem)
);
} else {
return otherArrays.some((otherArray) => otherArray.includes(subjectItem));
}
});
}
// =======================================
// The usage
// =======================================
const cheeseList = ["stilton", "edam", "cheddar", "brie"];
const foodListCollection = [
["cakes", "ham", "stilton"],
["juice", "wine", "brie", "bread", "stilton"]
];
// Output will be: ['stilton', 'brie']
const inclusive = assoc(cheeseList, foodListCollection, { mustBeInAll: false }),
// Output will be: ['stilton']
const exclusive = assoc(cheeseList, foodListCollection, { mustBeInAll: true })
实例:https://codesandbox.io/s/zealous-butterfly-h7dgf?fontsize=14&hidenavigation=1&theme=dark
function intersection(A,B){
var result = new Array();
for (i=0; i<A.length; i++) {
for (j=0; j<B.length; j++) {
if (A[i] == B[j] && $.inArray(A[i],result) == -1) {
result.push(A[i]);
}
}
}
return result;
}
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) );