用javascript实现数组交叉的最简单、无库代码是什么?我想写

intersection([1,2,3], [2,3,4,5])

并获得

[2, 3]

当前回答

在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()

其他回答

我写了一个相交函数,它甚至可以根据对象的特定属性来检测对象数组的交集。

例如,

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])

还要注意:该函数查找交集时考虑到第一个数组是主数组,因此交集结果将是主数组的结果。

通过使用.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要快三倍。

最简单、最快的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,然后再转换回数组。不需要任何额外的选角。

使用Underscore.js或lodash.js

_.intersection( [0,345,324] , [1,0,324] )  // gives [0,324]

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) );