我想了解从另一个数组的所有元素中过滤一个数组的最佳方法。我尝试了过滤功能,但它不来我如何给它的值,我想删除。喜欢的东西:

var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallback);
// filteredArray should now be [1,3]


function myCallBack(){
    return element ! filteredArray; 
    //which clearly can't work since we don't have the reference <,< 
}

如果过滤器函数没有用处,您将如何实现它? 编辑:我检查了可能的重复问题,这可能对那些容易理解javascript的人有用。如果答案勾选“好”,事情就简单多了。


当前回答

如果你想过滤一个具有一些匹配属性的不同结构的数组,你应该这样做。

let filteredArray = [];

array1.map(array1Item => {
array2.map(array2Item => {
  if (array1.property1 === array2.property2) {
    filteredArray.push(array1Item);
  }
});

这会让你的生活变得轻松!

其他回答

All the above solutions "work", but are less than optimal for performance and are all approach the problem in the same way which is linearly searching all entries at each point using Array.prototype.indexOf or Array.prototype.includes. A far faster solution (far faster even than a binary search for most cases) would be to sort the arrays and skip ahead as you go along as seen below. However, one downside is that this requires all entries in the array to be numbers or strings. Also however, binary search may in some rare cases be faster than the progressive linear search. These cases arise from the fact that my progressive linear search has a complexity of O(2n1+n2) (only O(n1+n2) in the faster C/C++ version) (where n1 is the searched array and n2 is the filter array), whereas the binary search has a complexity of O(n1ceil(log2n2)) (ceil = round up -- to the ceiling), and, lastly, the indexOf search has a highly variable complexity between O(n1) and O(n1n2), averaging out to O(n1ceil(n2÷2)). Thus, indexOf will only be the fastest, on average, in the cases of (n1,n2) equaling {1,2}, {1,3}, or {x,1|x∈N}. However, this is still not a perfect representation of modern hardware. IndexOf is natively optimized to the fullest extent imaginable in most modern browsers, making it very subject to the laws of branch prediction. Thus, if we make the same assumption on indexOf as we do with progressive linear and binary search -- that the array is presorted -- then, according to the stats listed in the link, we can expect roughly a 6x speed up for IndexOf, shifting its complexity to between O(n1÷6) and O(n1n2), averaging out to O(n1ceil(n27÷12)). Finally, take note that the below solution will never work with objects because objects in JavaScript cannot be compared by pointers in JavaScript.

function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
    var out=[], value=0;
    for (var i=0,  len=array.length|0; i < len; i=i+1|0)
        if (handle(value = array[i])) 
            out.push( value );
    return out;
}

const Math_clz32 = Math.clz32 || (function(log, LN2){
  return function(x) {
    return 31 - log(x >>> 0) / LN2 | 0; // the "| 0" acts like math.floor
  };
})(Math.log, Math.LN2);

/* USAGE:
  filterArrayByAnotherArray(
      [1,3,5],
      [2,3,4]
  ) yields [1, 5], and it can work with strings too
*/
function filterArrayByAnotherArray(searchArray, filterArray) {
    if (
        // NOTE: This does not check the whole array. But, if you know
        //        that there are only strings or numbers (not a mix of
        //        both) in the array, then this is a safe assumption.
        // Always use `==` with `typeof` because browsers can optimize
        //  the `==` into `===` (ONLY IN THIS CIRCUMSTANCE)
        typeof searchArray[0] == "number" &&
        typeof filterArray[0] == "number" &&
        (searchArray[0]|0) === searchArray[0] &&
        (filterArray[0]|0) === filterArray[0]
    ) {filterArray
        // if all entries in both arrays are integers
        searchArray.sort(sortIntArray);
        filterArray.sort(sortIntArray);
    } else {
        searchArray.sort(sortAnyArray);
        filterArray.sort(sortAnyArray);
    }
    var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
    var progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
    var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
    // After computing the complexity, we can predict which algorithm will be the fastest
    var i = 0;
    if (progressiveLinearComplexity < binarySearchComplexity) {
        // Progressive Linear Search
        return fastFilter(searchArray, function(currentValue){
            while (filterArray[i] < currentValue) i=i+1|0;
            // +undefined = NaN, which is always false for <, avoiding an infinite loop
            return filterArray[i] !== currentValue;
        });
    } else {
        // Binary Search
        return fastFilter(
            searchArray,
            fastestBinarySearch(filterArray)
        );
    }
}

// see https://stackoverflow.com/a/44981570/5601591 for implementation
//  details about this binary search algorithm

function fastestBinarySearch(array){
  var initLen = (array.length|0) - 1 |0;
  
  const compGoto = Math_clz32(initLen) & 31;
  return function(sValue) {
    var len = initLen |0;
    switch (compGoto) {
      case 0:
        if (len & 0x80000000) {
          const nCB = len & 0x80000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 1:
        if (len & 0x40000000) {
          const nCB = len & 0xc0000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 2:
        if (len & 0x20000000) {
          const nCB = len & 0xe0000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 3:
        if (len & 0x10000000) {
          const nCB = len & 0xf0000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 4:
        if (len & 0x8000000) {
          const nCB = len & 0xf8000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 5:
        if (len & 0x4000000) {
          const nCB = len & 0xfc000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 6:
        if (len & 0x2000000) {
          const nCB = len & 0xfe000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 7:
        if (len & 0x1000000) {
          const nCB = len & 0xff000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 8:
        if (len & 0x800000) {
          const nCB = len & 0xff800000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 9:
        if (len & 0x400000) {
          const nCB = len & 0xffc00000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 10:
        if (len & 0x200000) {
          const nCB = len & 0xffe00000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 11:
        if (len & 0x100000) {
          const nCB = len & 0xfff00000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 12:
        if (len & 0x80000) {
          const nCB = len & 0xfff80000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 13:
        if (len & 0x40000) {
          const nCB = len & 0xfffc0000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 14:
        if (len & 0x20000) {
          const nCB = len & 0xfffe0000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 15:
        if (len & 0x10000) {
          const nCB = len & 0xffff0000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 16:
        if (len & 0x8000) {
          const nCB = len & 0xffff8000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 17:
        if (len & 0x4000) {
          const nCB = len & 0xffffc000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 18:
        if (len & 0x2000) {
          const nCB = len & 0xffffe000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 19:
        if (len & 0x1000) {
          const nCB = len & 0xfffff000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 20:
        if (len & 0x800) {
          const nCB = len & 0xfffff800;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 21:
        if (len & 0x400) {
          const nCB = len & 0xfffffc00;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 22:
        if (len & 0x200) {
          const nCB = len & 0xfffffe00;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 23:
        if (len & 0x100) {
          const nCB = len & 0xffffff00;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 24:
        if (len & 0x80) {
          const nCB = len & 0xffffff80;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 25:
        if (len & 0x40) {
          const nCB = len & 0xffffffc0;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 26:
        if (len & 0x20) {
          const nCB = len & 0xffffffe0;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 27:
        if (len & 0x10) {
          const nCB = len & 0xfffffff0;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 28:
        if (len & 0x8) {
          const nCB = len & 0xfffffff8;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 29:
        if (len & 0x4) {
          const nCB = len & 0xfffffffc;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 30:
        if (len & 0x2) {
          const nCB = len & 0xfffffffe;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 31:
        if (len & 0x1) {
          const nCB = len & 0xffffffff;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
    }
    // MODIFICATION: Instead of returning the index, this binary search
    //                instead returns whether something was found or not.
    if (array[len|0] !== sValue) {
       return true; // preserve the value at this index
    } else {
       return false; // eliminate the value at this index
    }
  };
}

请参阅我的另一篇文章在这里使用二进制搜索算法的更多细节

如果您对文件大小很挑剔(我尊重这一点),那么您可以牺牲一点性能,以大大减小文件大小并提高可维护性。

function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
    var out=[], value=0;
    for (var i=0,  len=array.length|0; i < len; i=i+1|0)
        if (handle(value = array[i])) 
            out.push( value );
    return out;
}

/* USAGE:
  filterArrayByAnotherArray(
      [1,3,5],
      [2,3,4]
  ) yields [1, 5], and it can work with strings too
*/
function filterArrayByAnotherArray(searchArray, filterArray) {
    if (
        // NOTE: This does not check the whole array. But, if you know
        //        that there are only strings or numbers (not a mix of
        //        both) in the array, then this is a safe assumption.
        typeof searchArray[0] == "number" &&
        typeof filterArray[0] == "number" &&
        (searchArray[0]|0) === searchArray[0] &&
        (filterArray[0]|0) === filterArray[0]
    ) {
        // if all entries in both arrays are integers
        searchArray.sort(sortIntArray);
        filterArray.sort(sortIntArray);
    } else {
        searchArray.sort(sortAnyArray);
        filterArray.sort(sortAnyArray);
    }
    // Progressive Linear Search
    var i = 0;
    return fastFilter(searchArray, function(currentValue){
        while (filterArray[i] < currentValue) i=i+1|0;
        // +undefined = NaN, which is always false for <, avoiding an infinite loop
        return filterArray[i] !== currentValue;
    });
}

To prove the difference in speed, let us examine some JSPerfs. For filtering an array of 16 elements, binary search is roughly 17% faster than indexOf while filterArrayByAnotherArray is roughly 93% faster than indexOf. For filtering an array of 256 elements, binary search is roughly 291% faster than indexOf while filterArrayByAnotherArray is roughly 353% faster than indexOf. For filtering an array of 4096 elements, binary search is roughly 2655% faster than indexOf while filterArrayByAnotherArray is roughly 4627% faster than indexOf.

反向滤波(如与门)

上一节提供了获取数组A和数组B的代码,并删除A中存在于B中的所有元素:

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

下一节将提供反向过滤的代码,其中我们从A中删除B中不存在的所有元素。这个过程在功能上相当于只保留A和B的公共元素,如and门:

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

下面是反向过滤的代码:

function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
    var out=[], value=0;
    for (var i=0,  len=array.length|0; i < len; i=i+1|0)
        if (handle(value = array[i])) 
            out.push( value );
    return out;
}

const Math_clz32 = Math.clz32 || (function(log, LN2){
  return function(x) {
    return 31 - log(x >>> 0) / LN2 | 0; // the "| 0" acts like math.floor
  };
})(Math.log, Math.LN2);

/* USAGE:
  reverseFilterArrayByAnotherArray(
      [1,3,5],
      [2,3,4]
  ) yields [3], and it can work with strings too
*/
function reverseFilterArrayByAnotherArray(searchArray, filterArray) {
    if (
        // NOTE: This does not check the whole array. But, if you know
        //        that there are only strings or numbers (not a mix of
        //        both) in the array, then this is a safe assumption.
        // Always use `==` with `typeof` because browsers can optimize
        //  the `==` into `===` (ONLY IN THIS CIRCUMSTANCE)
        typeof searchArray[0] == "number" &&
        typeof filterArray[0] == "number" &&
        (searchArray[0]|0) === searchArray[0] &&
        (filterArray[0]|0) === filterArray[0]
    ) {
        // if all entries in both arrays are integers
        searchArray.sort(sortIntArray);
        filterArray.sort(sortIntArray);
    } else {
        searchArray.sort(sortAnyArray);
        filterArray.sort(sortAnyArray);
    }
    var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
    var progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
    var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
    // After computing the complexity, we can predict which algorithm will be the fastest
    var i = 0;
    if (progressiveLinearComplexity < binarySearchComplexity) {
        // Progressive Linear Search
        return fastFilter(searchArray, function(currentValue){
            while (filterArray[i] < currentValue) i=i+1|0;
            // +undefined = NaN, which is always false for <, avoiding an infinite loop
            // For reverse filterning, I changed !== to ===
            return filterArray[i] === currentValue;
        });
    } else {
        // Binary Search
        return fastFilter(
            searchArray,
            inverseFastestBinarySearch(filterArray)
        );
    }
}

// see https://stackoverflow.com/a/44981570/5601591 for implementation
//  details about this binary search algorithim

function inverseFastestBinarySearch(array){
  var initLen = (array.length|0) - 1 |0;
  
  const compGoto = Math_clz32(initLen) & 31;
  return function(sValue) {
    var len = initLen |0;
    switch (compGoto) {
      case 0:
        if (len & 0x80000000) {
          const nCB = len & 0x80000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 1:
        if (len & 0x40000000) {
          const nCB = len & 0xc0000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 2:
        if (len & 0x20000000) {
          const nCB = len & 0xe0000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 3:
        if (len & 0x10000000) {
          const nCB = len & 0xf0000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 4:
        if (len & 0x8000000) {
          const nCB = len & 0xf8000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 5:
        if (len & 0x4000000) {
          const nCB = len & 0xfc000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 6:
        if (len & 0x2000000) {
          const nCB = len & 0xfe000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 7:
        if (len & 0x1000000) {
          const nCB = len & 0xff000000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 8:
        if (len & 0x800000) {
          const nCB = len & 0xff800000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 9:
        if (len & 0x400000) {
          const nCB = len & 0xffc00000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 10:
        if (len & 0x200000) {
          const nCB = len & 0xffe00000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 11:
        if (len & 0x100000) {
          const nCB = len & 0xfff00000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 12:
        if (len & 0x80000) {
          const nCB = len & 0xfff80000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 13:
        if (len & 0x40000) {
          const nCB = len & 0xfffc0000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 14:
        if (len & 0x20000) {
          const nCB = len & 0xfffe0000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 15:
        if (len & 0x10000) {
          const nCB = len & 0xffff0000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 16:
        if (len & 0x8000) {
          const nCB = len & 0xffff8000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 17:
        if (len & 0x4000) {
          const nCB = len & 0xffffc000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 18:
        if (len & 0x2000) {
          const nCB = len & 0xffffe000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 19:
        if (len & 0x1000) {
          const nCB = len & 0xfffff000;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 20:
        if (len & 0x800) {
          const nCB = len & 0xfffff800;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 21:
        if (len & 0x400) {
          const nCB = len & 0xfffffc00;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 22:
        if (len & 0x200) {
          const nCB = len & 0xfffffe00;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 23:
        if (len & 0x100) {
          const nCB = len & 0xffffff00;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 24:
        if (len & 0x80) {
          const nCB = len & 0xffffff80;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 25:
        if (len & 0x40) {
          const nCB = len & 0xffffffc0;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 26:
        if (len & 0x20) {
          const nCB = len & 0xffffffe0;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 27:
        if (len & 0x10) {
          const nCB = len & 0xfffffff0;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 28:
        if (len & 0x8) {
          const nCB = len & 0xfffffff8;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 29:
        if (len & 0x4) {
          const nCB = len & 0xfffffffc;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 30:
        if (len & 0x2) {
          const nCB = len & 0xfffffffe;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
      case 31:
        if (len & 0x1) {
          const nCB = len & 0xffffffff;
          len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
        }
    }
    // MODIFICATION: Instead of returning the index, this binary search
    //                instead returns whether something was found or not.
    // For reverse filterning, I swapped true with false and vice-versa
    if (array[len|0] !== sValue) {
       return false; // preserve the value at this index
    } else {
       return true; // eliminate the value at this index
    }
  };
}

有关反向过滤代码的较慢的较小版本,请参见下面。

function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
function fastFilter(array, handle) {
    var out=[], value=0;
    for (var i=0,  len=array.length|0; i < len; i=i+1|0)
        if (handle(value = array[i])) 
            out.push( value );
    return out;
}

/* USAGE:
  reverseFilterArrayByAnotherArray(
      [1,3,5],
      [2,3,4]
  ) yields [3], and it can work with strings too
*/
function reverseFilterArrayByAnotherArray(searchArray, filterArray) {
    if (
        // NOTE: This does not check the whole array. But, if you know
        //        that there are only strings or numbers (not a mix of
        //        both) in the array, then this is a safe assumption.
        typeof searchArray[0] == "number" &&
        typeof filterArray[0] == "number" &&
        (searchArray[0]|0) === searchArray[0] &&
        (filterArray[0]|0) === filterArray[0]
    ) {
        // if all entries in both arrays are integers
        searchArray.sort(sortIntArray);
        filterArray.sort(sortIntArray);
    } else {
        searchArray.sort(sortAnyArray);
        filterArray.sort(sortAnyArray);
    }
    // Progressive Linear Search
    var i = 0;
    return fastFilter(searchArray, function(currentValue){
        while (filterArray[i] < currentValue) i=i+1|0;
        // +undefined = NaN, which is always false for <, avoiding an infinite loop
        // For reverse filter, I changed !== to ===
        return filterArray[i] === currentValue;
    });
}

Jack Giffin的解决方案很好,但不适用于大于2^32的数组。下面是基于Jack的解决方案来过滤数组的重构快速版本,但它适用于64位数组。

const Math_clz32 = Math.clz32 || ((log, LN2) => x => 31 - log(x >>> 0) / LN2 | 0)(Math.log, Math.LN2);

const filterArrayByAnotherArray = (searchArray, filterArray) => {

    searchArray.sort((a,b) => a > b);
    filterArray.sort((a,b) => a > b);

    let searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
    let progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
    let binarySearchComplexity = (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;

    let i = 0;

    if (progressiveLinearComplexity < binarySearchComplexity) {
      return searchArray.filter(currentValue => {
        while (filterArray[i] < currentValue) i=i+1|0;
        return filterArray[i] !== currentValue;
      });
    }
    else return searchArray.filter(e => binarySearch(filterArray, e) === null);
}

const binarySearch = (sortedArray, elToFind) => {
  let lowIndex = 0;
  let highIndex = sortedArray.length - 1;
  while (lowIndex <= highIndex) {
    let midIndex = Math.floor((lowIndex + highIndex) / 2);
    if (sortedArray[midIndex] == elToFind) return midIndex; 
    else if (sortedArray[midIndex] < elToFind) lowIndex = midIndex + 1;
    else highIndex = midIndex - 1;
  } return null;
}

下面的例子使用new Set()创建一个只有唯一元素的过滤数组:

数组的基本数据类型:字符串,数字,布尔,空,未定义,符号:

const a = [1, 2, 3, 4];
const b = [3, 4, 5];
const c = Array.from(new Set(a.concat(b)));

以对象为项的数组:

const a = [{id:1}, {id: 2}, {id: 3}, {id: 4}];
const b = [{id: 3}, {id: 4}, {id: 5}];
const stringifyObject = o => JSON.stringify(o);
const parseString = s => JSON.parse(s);
const c = Array.from(new Set(a.concat(b).map(stringifyObject)), parseString);
var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallBack);

function myCallBack(el){
  return anotherOne.indexOf(el) < 0;
}

在回调中,检查数组的每个值是否在另一个数组中

https://jsfiddle.net/0tsyc1sx/

如果使用lodash.js,请使用_.difference

filteredArray = _.difference(array, anotherOne);

Demo

如果你有一个对象数组:

var array = [{id :1, name :"test1"},{id :2, name :"test2"},{id :3, name :"test3"},{id :4, name :"test4"}];

var anotherOne = [{id :2, name :"test2"}, {id :4, name :"test4"}];

var filteredArray  = array.filter(function(array_el){
   return anotherOne.filter(function(anotherOne_el){
      return anotherOne_el.id == array_el.id;
   }).length == 0
});

对象的演示数组

用lodash演示不同的对象数组

下面是当数组中的项是对象时的操作方法。

其思想是使用map函数在内部数组中查找仅包含键的数组

然后检查这些键的数组是否包含外层数组中的特定元素键。

const existsInBothArrays = array1.filter((element1) =>
    array2.map((element2) => element2._searchKey).includes(element1._searchKey),
  );