javascript中数组交集的最简单代码

时间:2009-12-11 03:04:05

标签: javascript data-structures intersection

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

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

并获取

[2, 3]

48 个答案:

答案 0 :(得分:865)

使用Array.prototype.filterArray.prototype.indexOf的组合:

array1.filter(value => -1 !== array2.indexOf(value))

或者在评论中建议使用vrugtehagel,您可以使用更新的Array.prototype.includes来获得更简单的代码:

array1.filter(value => array2.includes(value))

对于旧版浏览器:

array1.filter(function(n) {
    return array2.indexOf(n) !== -1;
});

答案 1 :(得分:155)

破坏性似乎最简单,特别是如果我们可以假设输入已经排序:

/* destructively finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *  State of input arrays is undefined when
 *  the function returns.  They should be 
 *  (prolly) be dumped.
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length, b.length)
 */
function intersection_destructive(a, b)
{
  var result = [];
  while( a.length > 0 && b.length > 0 )
  {  
     if      (a[0] < b[0] ){ a.shift(); }
     else if (a[0] > b[0] ){ b.shift(); }
     else /* they're equal */
     {
       result.push(a.shift());
       b.shift();
     }
  }

  return result;
}

非破坏性必须更复杂,因为我们必须跟踪指数:

/* finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length(), b.length())
 */
function intersect_safe(a, b)
{
  var ai=0, bi=0;
  var result = [];

  while( ai < a.length && bi < b.length )
  {
     if      (a[ai] < b[bi] ){ ai++; }
     else if (a[ai] > b[bi] ){ bi++; }
     else /* they're equal */
     {
       result.push(a[ai]);
       ai++;
       bi++;
     }
  }

  return result;
}

答案 2 :(得分:46)

如果你的环境支持ECMAScript 6 Set,那么一个简单且有效的(见规范链接)方式:

function intersect(a, b) {
  var setA = new Set(a);
  var setB = new Set(b);
  var intersection = new Set([...setA].filter(x => setB.has(x)));
  return Array.from(intersection);
}

更短,但可读性更低(也没有创建额外的交集Set):

function intersect(a, b) {
      return [...new Set(a)].filter(x => new Set(b).has(x));
}

每次从Set避免新的b

function intersect(a, b) {
      var setB = new Set(b);
      return [...new Set(a)].filter(x => setB.has(x));
}

请注意,使用套装时,您只会获得不同的值,因此new Set[1,2,3,3].size的评估结果为3

答案 3 :(得分:28)

使用 Underscore.js lodash.js

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

答案 4 :(得分:12)

我在ES6方面的贡献。通常,它会找到一个数组的交集,该数组具有作为参数提供的无限数量的数组。

&#13;
&#13;
Array.prototype.intersect = function(...a) {
  return [this,...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];

document.write("<pre>" + JSON.stringify(arr.intersect(...arrs)) + "</pre>");
&#13;
&#13;
&#13;

答案 5 :(得分:11)

如何使用关联数组?

function intersect(a, b) {
    var d1 = {};
    var d2 = {};
    var results = [];
    for (var i = 0; i < a.length; i++) {
        d1[a[i]] = true;
    }
    for (var j = 0; j < b.length; j++) {
        d2[b[j]] = true;
    }
    for (var k in d1) {
        if (d2[k]) 
            results.push(k);
    }
    return results;
}

编辑:

// new version
function intersect(a, b) {
    var d = {};
    var results = [];
    for (var i = 0; i < b.length; i++) {
        d[b[i]] = true;
    }
    for (var j = 0; j < a.length; j++) {
        if (d[a[j]]) 
            results.push(a[j]);
    }
    return results;
}

答案 6 :(得分:8)

使用.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创建了一个基准:http://bit.ly/P9FrZK。它的使用速度快了三倍.pop。

答案 7 :(得分:8)

使用 jQuery

var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);

答案 8 :(得分:7)

  1. 排序
  2. 从索引0逐个检查,从中创建新数组。
  3. 这样的事情,虽然测试不好。

    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:该算法仅适用于Numbers和Normal Strings,仲裁对象数组的交集可能不起作用。

答案 9 :(得分:7)

对于仅包含字符串或数字的数组,您可以根据其他一些答案执行排序操作。对于任意对象数组的一般情况,我认为你不能避免长期使用它。以下内容将为您提供作为arrayIntersection的参数提供的任意数量的数组的交集:

var arrayContains = Array.prototype.indexOf ?
    function(arr, val) {
        return arr.indexOf(val) > -1;
    } :
    function(arr, val) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) {
                return true;
            }
        }
        return false;
    };

function arrayIntersection() {
    var val, arrayCount, firstArray, i, j, intersection = [], missing;
    var arrays = Array.prototype.slice.call(arguments); // Convert arguments into a real array

    // Search for common values
    firstArray = arrays.pop();
    if (firstArray) {
        j = firstArray.length;
        arrayCount = arrays.length;
        while (j--) {
            val = firstArray[j];
            missing = false;

            // Check val is present in each remaining array 
            i = arrayCount;
            while (!missing && i--) {
                if ( !arrayContains(arrays[i], val) ) {
                    missing = true;
                }
            }
            if (!missing) {
                intersection.push(val);
            }
        }
    }
    return intersection;
}

arrayIntersection( [1, 2, 3, "a"], [1, "a", 2], ["a", 1] ); // Gives [1, "a"]; 

答案 10 :(得分:7)

使用ES2015和套装非常简短。接受类似于String的类似数组的值并删除重复项。

&#13;
&#13;
let intersection = function(a, b) {
  a = new Set(a), b = new Set(b);
  return [...a].filter(v => b.has(v));
};

console.log(intersection([1,2,1,2,3], [2,3,5,4,5,3]));

console.log(intersection('ccaabbab', 'addb').join(''));
&#13;
&#13;
&#13;

答案 11 :(得分:5)

另一种能够同时处理任意数量数组的索引方法:

// 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"]

编辑:我刚才注意到,这在某种程度上是轻微的错误。

那就是:我编码认为输入数组本身不能包含重复(如示例所示)。

但是如果输入数组恰好包含重复,那么会产生错误的结果。示例(使用以下实现):

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]

幸运的是,只需添加第二级索引即可轻松解决此问题。那就是:

变化:

        if (index[v] === undefined) index[v] = 0;
        index[v]++;

由:

        if (index[v] === undefined) index[v] = {};
        index[v][i] = true; // Mark as present in i input.

...和

         if (index[i] == arrLength) retv.push(i);

由:

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

答案 12 :(得分:5)

对这里最小的一个微调(filter/indexOf solution),即使用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()的常数因子慢),但看起来非常好平衡。它位于非常简单的一面,同时提供良好的性能,并且不需要预先排序的输入。

答案 13 :(得分:4)

对您的数据有一些限制,您可以在线性时间内完成!

对于正整数:使用数组将值映射到“看到/未看到”布尔值。

function intersectIntegers(array1,array2) { 
   var seen=[],
       result=[];
   for (var i = 0; i < array1.length; i++) {
     seen[array1[i]] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if ( seen[array2[i]])
        result.push(array2[i]);
   }
   return result;
}

对于对象有类似的技术:获取一个虚拟键,为array1中的每个元素设置为“true”,然后在array2的元素中查找此键。完成后清理。

function intersectObjects(array1,array2) { 
   var result=[];
   var key="tmpKey_intersect"
   for (var i = 0; i < array1.length; i++) {
     array1[i][key] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if (array2[i][key])
        result.push(array2[i]);
   }
   for (var i = 0; i < array1.length; i++) {
     delete array1[i][key];
   }
   return result;
}

当然你需要确保密钥没有出现,否则你将破坏你的数据......

答案 14 :(得分:4)

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

答案 15 :(得分:3)

这可能是最简单的一个, 除 list1.filter(n =&gt; list2.includes(n))

var list1 = ['bread', 'ice cream', 'cereals', 'strawberry', 'chocolate']
var list2 = ['bread', 'cherry', 'ice cream', 'oats']

function check_common(list1, list2){
	
	list3 = []
	for (let i=0; i<list1.length; i++){
		
		for (let j=0; j<list2.length; j++){	
			if (list1[i] === list2[j]){
				list3.push(list1[i]);				
			}		
		}
		
	}
	return list3
	
}

check_common(list1, list2) // ["bread", "ice cream"]

答案 16 :(得分:3)

我会为最适合我的事情做出贡献:

if (!Array.prototype.intersect){
Array.prototype.intersect = function (arr1) {

    var r = [], o = {}, l = this.length, i, v;
    for (i = 0; i < l; i++) {
        o[this[i]] = true;
    }
    l = arr1.length;
    for (i = 0; i < l; i++) {
        v = arr1[i];
        if (v in o) {
            r.push(v);
        }
    }
    return r;
};
}

答案 17 :(得分:3)

“indexOf”适用于IE 9.0,chrome,firefox,opera,

    function intersection(a,b){
     var rs = [], x = a.length;
     while (x--) b.indexOf(a[x])!=-1 && rs.push(a[x]);
     return rs.sort();
    }

intersection([1,2,3], [2,3,4,5]);
//Result:  [2,3]

答案 18 :(得分:2)

'use strict'

// Example 1
function intersection(a1, a2) {
    return a1.filter(x => a2.indexOf(x) > -1)
}

// Example 2 (prototype function)
Array.prototype.intersection = function(arr) {
    return this.filter(x => arr.indexOf(x) > -1)
} 

const a1 = [1, 2, 3]
const a2 = [2, 3, 4, 5]

console.log(intersection(a1, a2))
console.log(a1.intersection(a2))

答案 19 :(得分:2)

.reduce用于构建地图,.filter用于查找交叉点。 delete中的.filter允许我们将第二个数组视为唯一集合。

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

我发现这种方法很容易理解。它会在恒定的时间内执行。

答案 20 :(得分:2)

为简单起见:

// Usage
const intersection = allLists
  .reduce(intersect, allValues)
  .reduce(removeDuplicates, []);


// Implementation
const intersect = (intersection, list) =>
  intersection.filter(item =>
    list.some(x => x === item));

const removeDuplicates = (uniques, item) =>
  uniques.includes(item) ? uniques : uniques.concat(item);


// Example Data
const somePeople = [bob, doug, jill];
const otherPeople = [sarah, bob, jill];
const morePeople = [jack, jill];

const allPeople = [...somePeople, ...otherPeople, ...morePeople];
const allGroups = [somePeople, otherPeople, morePeople];

// Example Usage
const intersection = allGroups
  .reduce(intersect, allPeople)
  .reduce(removeDuplicates, []);

intersection; // [jill]

优点:

  • 污垢简单
  • 数据为中心的
  • 适用于任意数量的列表
  • 适用于任意长度的列表
  • 适用于任意类型的值
  • 适用于任意排序顺序
  • 保留形状(任何阵列中首次出现的顺序)
  • 尽可能早退出
  • 内存安全,没有篡改功能/阵列原型

缺点:

  • 更高的内存使用量
  • 更高的CPU使用率
  • 需要了解reduce
  • 需要了解数据流

您不希望将此用于3D引擎或内核工作,但如果您在基于事件的应用程序中运行此问题时遇到问题,那么您的设计会遇到更大的问题。

答案 21 :(得分:2)

使用ES2015的功能方法

功能性方法必须考虑仅使用没有副作用的纯函数,每个函数仅涉及单个作业。

这些限制增强了所涉及功能的可组合性和可重用性。

// small, reusable auxiliary functions

const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const apply = f => x => f(x);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run it

console.log( intersect(xs) (ys) );

请注意,使用了原生的Set类型,这是有利的 查找性能。

避免重复

显然,第一个Array中重复出现的项目会被保留,而第二个Array会被重复删除。这可能是或可能不是期望的行为。如果您需要唯一的结果,只需将dedupe应用于第一个参数:

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

计算任意数量的Array s

的交集

如果您想计算任意数量Array的交集,只需将intersectfoldl进行比较。这是一个便利功能:

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

答案 22 :(得分:1)

如果要使用接受的答案,但需要Internet Explorer的支持,则必须避免使用箭头功能的简写注释。这是经过编辑的单行代码,也可以在IE中使用:

// accepted aswer: array1.filter(value => -1 !== array2.indexOf(value));
// IE-supported syntax:
array1.filter(function(value) { return -1 !== array2.indexOf(value) });

答案 23 :(得分:1)

您可以将Set中的Array#filter用作thisArg,并以Set#has作为回调。

function intersection(a, b) {
    return a.filter(Set.prototype.has, new Set(b));
}

console.log(intersection([1, 2, 3], [2, 3, 4, 5]));

答案 24 :(得分:1)

除了使用indexOf之外,您还可以使用Array.protype.includes

function intersection(arr1, arr2) {
  return arr1.filter((ele => {
    return arr2.includes(ele);
  }));
}

console.log(intersection([1,2,3], [2,3,4,5]));

答案 25 :(得分:1)

ES6样式简单的方法。

const intersection = (a, b) => {
  const s = new Set(b);
  return a.filter(x => s.has(x));
};

示例:

intersection([1, 2, 3], [4, 3, 2]); // [2, 3]

答案 26 :(得分:1)

如果你需要让它处理多个数组相交:

selection

答案 27 :(得分:1)

自ECMA 2016起,您只能使用:

const intersection = (arr1, arr2) => arr1.filter(el => arr2.includes(el));

答案 28 :(得分:1)

这个函数避免了N^2问题,利用了字典的力量。只循环遍历每个数组一次,第三次或更短的循环返回最终结果。 它还支持数字、字符串和对象

function array_intersect(array1, array2) 
{
    var mergedElems = {},
        result = [];

    // Returns a unique reference string for the type and value of the element
    function generateStrKey(elem) {
        var typeOfElem = typeof elem;
        if (typeOfElem === 'object') {
            typeOfElem += Object.prototype.toString.call(elem);
        }
        return [typeOfElem, elem.toString(), JSON.stringify(elem)].join('__');
    }

    array1.forEach(function(elem) {
        var key = generateStrKey(elem);
        if (!(key in mergedElems)) {
            mergedElems[key] = {elem: elem, inArray2: false};
        }
    });

    array2.forEach(function(elem) {
        var key = generateStrKey(elem);
        if (key in mergedElems) {
            mergedElems[key].inArray2 = true;
        }
    });

    Object.values(mergedElems).forEach(function(elem) {
        if (elem.inArray2) {
            result.push(elem.elem);
        }
    });

    return result;
}

如果有无法解决的特殊情况,只要修改generateStrKey函数,肯定可以解决。这个函数的诀窍在于它根据类型和值唯一地表示每个不同的数据。


此变体有一些性能改进。避免循环,以防任何数组为空。它还首先遍历较短的数组,因此如果它在第二个数组中找到第一个数组的所有值,则退出循环。

function array_intersect(array1, array2) 
{
    var mergedElems = {},
        result = [],
        firstArray, secondArray,
        firstN = 0, 
        secondN = 0;

    function generateStrKey(elem) {
        var typeOfElem = typeof elem;
        if (typeOfElem === 'object') {
            typeOfElem += Object.prototype.toString.call(elem);
        }
        return [typeOfElem, elem.toString(), JSON.stringify(elem)].join('__');
    }

    // Executes the loops only if both arrays have values
    if (array1.length && array2.length) 
    {
        // Begins with the shortest array to optimize the algorithm
        if (array1.length < array2.length) {
            firstArray = array1;
            secondArray = array2;
        } else {
            firstArray = array2;
            secondArray = array1;            
        }

        firstArray.forEach(function(elem) {
            var key = generateStrKey(elem);
            if (!(key in mergedElems)) {
                mergedElems[key] = {elem: elem, inArray2: false};
                // Increases the counter of unique values in the first array
                firstN++;
            }
        });

        secondArray.some(function(elem) {
            var key = generateStrKey(elem);
            if (key in mergedElems) {
                if (!mergedElems[key].inArray2) {
                    mergedElems[key].inArray2 = true;
                    // Increases the counter of matches
                    secondN++;
                    // If all elements of first array have coincidence, then exits the loop
                    return (secondN === firstN);
                }
            }
        });

        Object.values(mergedElems).forEach(function(elem) {
            if (elem.inArray2) {
                result.push(elem.elem);
            }
        });
    }

    return result;
}

答案 29 :(得分:1)

我编写了一个积分函数,该函数甚至可以根据那些对象的特定属性来检测对象数组的交集。

例如,

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

也请注意:考虑到第一个数组是主数组,此函数将找到交集,因此交集结果将是主数组的交集。

答案 30 :(得分:1)

var arrays = [
    [1, 2, 3],
    [2, 3, 4, 5]
]
function commonValue (...arr) {
    let res = arr[0].filter(function (x) {
        return arr.every((y) => y.includes(x))
    })
    return res;
}
commonValue(...arrays);

答案 31 :(得分:1)

function getIntersection(arr1, arr2){
    var result = [];
    arr1.forEach(function(elem){
        arr2.forEach(function(elem2){
            if(elem === elem2){
                result.push(elem);
            }
        });
    });
    return result;
}

getIntersection([1,2,3], [2,3,4,5]); // [ 2, 3 ]

答案 32 :(得分:1)

var listA = [1,2,3,4,5,6,7];
var listB = [2,4,6,8];

var result = listA.filter(itemA=> {
    return listB.some(itemB => itemB === itemA);
});

答案 33 :(得分:1)

以下是underscore.js实施:

_.intersection = function(array) {
  if (array == null) return [];
  var result = [];
  var argsLength = arguments.length;
  for (var i = 0, length = array.length; i < length; i++) {
    var item = array[i];
    if (_.contains(result, item)) continue;
    for (var j = 1; j < argsLength; j++) {
      if (!_.contains(arguments[j], item)) break;
    }
    if (j === argsLength) result.push(item);
  }
  return result;
};

来源:http://underscorejs.org/docs/underscore.html#section-62

答案 34 :(得分:0)

使用一个数组创建一个对象,然后遍历第二个数组以检查该值是否作为键存在。

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

答案 35 :(得分:0)

这是我正在使用的一个非常天真的实现。它是非破坏性的,也确保不会复制。

Array.prototype.contains = function(elem) {
    return(this.indexOf(elem) > -1);
};

Array.prototype.intersect = function( array ) {
    // this is naive--could use some optimization
    var result = [];
    for ( var i = 0; i < this.length; i++ ) {
        if ( array.contains(this[i]) && !result.contains(this[i]) )
            result.push( this[i] );
    }
    return result;
}

答案 36 :(得分:0)

coffeescript中的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()

答案 37 :(得分:0)

function intersectionOfArrays(arr1, arr2) {
    return arr1.filter((element) => arr2.indexOf(element) !== -1).filter((element, pos, self) => self.indexOf(element) == pos);
}

答案 38 :(得分:0)

以下代码也会删除重复项:

       function intersect(x, y) {
            if (y.length > x.length) temp = y, y = x, x= temp;  
            return x.filter(function (e, i, c) {  
                  return c.indexOf(e) === i;
                 });
       }

答案 39 :(得分:0)

我扩展了tarulen的答案,可以使用任意数量的数组。它也应该使用非整数值。

SELECT DISTINCT
CNT.ACCT_ID, 
COUNT(DISTINCT CNT.BILL_ID) AS BILLS,
TO_CHAR(SUM(CNT.CUR_AMT),'9,999,999') as TOTAL_BILLED,
TO_CHAR(SUM(CNT.CUR_AMT)/COUNT (DISTINCT CNT.BILL_ID),'999,999') as AVG_BILL

FROM
(SELECT 
        LC.ACCT_ID,
        BILL.BILL_ID,
        FT.CUR_AMT,
        BILL.BILL_DT

FROM table1.CUSTOMER_DEPOSITS LC,
table2.PS_CI_BSEG BSEG,
table3.PS_CI_BILL BILL,
table4.PS_CI_FT FT

WHERE
LC.ACCT_ID =BILL.ACCT_ID
AND LC.CUST_CLASS NOT IN ('PPAY-R','TAFT','C-TAFT','SP3','C-NPAY')
AND FT.BILL_ID = BILL.BILL_ID
AND FT.FT_TYPE_FLG = 'BS'
AND BSEG.BILL_ID = BILL.BILL_ID
AND BSEG.BSEG_STAT_FLG = '50' 
AND FT.ARS_DT > '01-JUN-2015'
AND FT.ARS_DT < '01-JUL-2016'
)CNT

GROUP BY CNT.ACCT_ID

答案 40 :(得分:0)

如果第二个数组总是要作为set处理,则无需在第二个数组的函数内部声明中间变量。

以下解决方案返回在两个数组中均出现的唯一值数组:

const intersection = (a, b) => {
  b = new Set(b); // recycling variable
  return [...new Set(a)].filter(e => b.has(e));
};

console.log(intersection([1, 2, 3, 1, 1], [1, 2, 4])); // Array [ 1, 2 ]

答案 41 :(得分:0)

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

答案 42 :(得分:0)

如果数组已排序,则应在O(n)中运行,其中n为min(a.length,b.length)

function intersect_1d( a, b ){
    var out=[], ai=0, bi=0, acurr, bcurr, last=Number.MIN_SAFE_INTEGER;
    while( ( acurr=a[ai] )!==undefined && ( bcurr=b[bi] )!==undefined ){
        if( acurr < bcurr){
            if( last===acurr ){
                out.push( acurr );
            }
            last=acurr;
            ai++;
        }
        else if( acurr > bcurr){
            if( last===bcurr ){
                out.push( bcurr );
            }
            last=bcurr;
            bi++;
        }
        else {
            out.push( acurr );
            last=acurr;
            ai++;
            bi++;
        }
    }
    return out;
}

答案 43 :(得分:0)

希望这有助于所有版本。

timeDate <- as.POSIXct(EURUSDtime$Date;Time, format = "%d.%m.%Y;%H:%M")

答案 44 :(得分:-1)

不是关于效率,而是易于遵循,这里是集合的联合和交集的一个例子,它处理集合和集合的数组。

http://jsfiddle.net/zhulien/NF68T/

// process array [element, element...], if allow abort ignore the result
function processArray(arr_a, cb_a, blnAllowAbort_a)
{
    var arrResult = [];
    var blnAborted = false;
    var intI = 0;

    while ((intI < arr_a.length) && (blnAborted === false))
    {
        if (blnAllowAbort_a)
        {
            blnAborted = cb_a(arr_a[intI]);
        }
        else
        {
            arrResult[intI] = cb_a(arr_a[intI]);
        }
        intI++;
    }

    return arrResult;
}

// process array of operations [operation,arguments...]
function processOperations(arrOperations_a)
{
    var arrResult = [];
    var fnOperationE;

    for(var intI = 0, intR = 0; intI < arrOperations_a.length; intI+=2, intR++) 
    {
        var fnOperation = arrOperations_a[intI+0];
        var fnArgs = arrOperations_a[intI+1];
        if (fnArgs === undefined)
        {
            arrResult[intR] = fnOperation();
        }
        else
        {
            arrResult[intR] = fnOperation(fnArgs);
        }
    }

    return arrResult;
}

// return whether an element exists in an array
function find(arr_a, varElement_a)
{
    var blnResult = false;

    processArray(arr_a, function(varToMatch_a)
    {
        var blnAbort = false;

        if (varToMatch_a === varElement_a)
        {
            blnResult = true;
            blnAbort = true;
        }

        return blnAbort;
    }, true);

    return blnResult;
}

// return the union of all sets
function union(arr_a)
{
    var arrResult = [];
    var intI = 0;

    processArray(arr_a, function(arrSet_a)
    {
        processArray(arrSet_a, function(varElement_a)
        {
            // if the element doesn't exist in our result
            if (find(arrResult, varElement_a) === false)
            {
                // add it
                arrResult[intI] = varElement_a;
                intI++;
            }
        });
    });

    return arrResult;
}

// return the intersection of all sets
function intersection(arr_a)
{
    var arrResult = [];
    var intI = 0;

    // for each set
    processArray(arr_a, function(arrSet_a)
    {
        // every number is a candidate
        processArray(arrSet_a, function(varCandidate_a)
        {
            var blnCandidate = true;

            // for each set
            processArray(arr_a, function(arrSet_a)
            {
                // check that the candidate exists
                var blnFoundPart = find(arrSet_a, varCandidate_a);

                // if the candidate does not exist
                if (blnFoundPart === false)
                {
                    // no longer a candidate
                    blnCandidate = false;
                }
            });

            if (blnCandidate)
            {
                // if the candidate doesn't exist in our result
                if (find(arrResult, varCandidate_a) === false)
                {
                    // add it
                    arrResult[intI] = varCandidate_a;
                    intI++;
                }
            }
        });
    });

    return arrResult;
}

var strOutput = ''

var arrSet1 = [1,2,3];
var arrSet2 = [2,5,6];
var arrSet3 = [7,8,9,2];

// return the union of the sets
strOutput = union([arrSet1, arrSet2, arrSet3]);
alert(strOutput);

// return the intersection of 3 sets
strOutput = intersection([arrSet1, arrSet2, arrSet3]);
alert(strOutput);

// of 3 sets of sets, which set is the intersecting set
strOutput = processOperations([intersection,[[arrSet1, arrSet2], [arrSet2], [arrSet2, arrSet3]]]);
alert(strOutput);

答案 45 :(得分:-1)

使用reduce

const intersection = (arrays) => { 
       return arrays.reduce((a, b) => a.filter((ele) => b.includes(ele))) 
 };

答案 46 :(得分:-1)

这是一种现代且简单的 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

答案 47 :(得分:-4)

IE中的Array不支持“filter”和“indexOf”。怎么样:

var array1 = [1, 2, 3];
var array2 = [2, 3, 4, 5];

var intersection = [];
for (i in array1) {
    for (j in array2) {
        if (array1[i] == array2[j]) intersection.push(array1[i]);
    }
}