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

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

并获得

[2, 3]

当前回答

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

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

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

当然,你需要确保这个键之前没有出现过,否则你会破坏你的数据…

其他回答

如果你的数组是排序的,这应该运行在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;
}

使用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。

如果只使用关联数组呢?

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

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

对于只包含字符串或数字的数组,你可以做一些排序,就像其他答案一样。对于任意对象数组的一般情况,我不认为你可以避免这样做。下面将为您提供任意数量的数组的交集作为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"];