【问题标题】:How to filter an array from all elements of another array如何从另一个数组的所有元素中过滤一个数组
【发布时间】:2016-04-26 09:22:12
【问题描述】:


我想了解从另一个数组的所有元素中过滤数组的最佳方法。我尝试使用过滤器功能,但我不知道如何给它我想要删除的值。
有点像:

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 的人有用。检查为好的答案使事情变得容易。

【问题讨论】:

  • 传递另一个数组过滤回调并使用return arrTwo.indexOf(e) === -1; 代码: var filteredArr = firstArr.filter(el =&gt; secondArr.indexOf(el) === -1);
  • 两个数组都排序了吗?
  • 数组是无序的,第二个数组的元素个数也是随机的。

标签: javascript arrays filter


【解决方案1】:

我会这样做;

var arr1 = [1,2,3,4],
    arr2 = [2,4],
    res = arr1.filter(item => !arr2.includes(item));
console.log(res);

【讨论】:

  • 摇滚明星。谢谢,这对于解决稍微不同的问题非常有帮助。根据反应组件中的值数组过滤出对象数组:const filteredResults = this.state.cards.filter( result =&gt; !this.state.filterOut.includes(result.category) ) 其中 this.state.cards 在对象数组中,this.state.filterOut 是对应于“类别”键的值数组我想删除的对象。
  • 我知道,这是一个较旧的回复,但我只是想让您知道我更喜欢这个回复,它帮助我解决了我遇到的一个问题。它非常易读,因此我更容易更好地理解这个问题。
  • includes 仅适用于 ES7。如果您使用 ES6,请使用公认的解决方案。
  • 箭头函数 FTW。比老派的回调好多了!
【解决方案2】:

您可以使用filter() 函数的this 参数来避免将过滤器数组存储在全局变量中。

var filtered = [1, 2, 3, 4].filter(
    function(e) {
      return this.indexOf(e) < 0;
    },
    [2, 4]
);
console.log(filtered);

【讨论】:

  • 它就像一个魅力。是否可以将函数移到外部并以更易于理解的方式调用它?比如: var filters=[1,2,3,4].filter(myfunct(),[2,4]);
  • 当然:var myFunct=function(e){return this.indexOf(e)
  • 这可以通过 ES2016 或 TypesScript 中的 lambda 表达式来实现吗?
  • 当我使用这种方法时,过滤器的第二个参数没有作为this 进入我的函数。 this 似乎总是未定义?!奇怪
【解决方案3】:
var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallBack);

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

在回调中,检查array 的每个值是否在anotherOne

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

Demo array of objects

Demo diff array of objects with lodash

【讨论】:

  • 嗨,你可以在对象数组中扩展这个吗?我将不胜感激
  • 你在使用 lodash 吗?
  • 不,先生,我更喜欢遵循回调方法
  • 好吧,先生,它确实有效,但除了 id 我如何用名字过滤其他方式?
  • 嗯...您只需使用您自己对象中的任何键更改anotherOne_el.id == array_el.id 中的id。您应该了解javascript中的数组和对象,它将帮助您更好地理解答案
【解决方案4】:

        /* Here's an example that uses (some) ES6 Javascript semantics to filter an object array by another object array. */

        // x = full dataset
        // y = filter dataset
        let x = [
            {"val": 1, "text": "a"},
            {"val": 2, "text": "b"},
            {"val": 3, "text": "c"},
            {"val": 4, "text": "d"},
            {"val": 5, "text": "e"}
            ],
            y = [
            {"val": 1, "text": "a"},
            {"val": 4, "text": "d"}               
            ];

        // Use map to get a simple array of "val" values. Ex: [1,4]
        let yFilter = y.map(itemY => { return itemY.val; });

        // Use filter and "not" includes to filter the full dataset by the filter dataset's val.
        let filteredX = x.filter(itemX => !yFilter.includes(itemX.val));

        // Print the result.
        console.log(filteredX);

【讨论】:

  • 正是我需要的。谢谢
  • 我不确定它是如何工作的,但稍作调整,它挽救了一天。谢谢。如果有人能解释这是如何工作的,那将非常有帮助
  • @ChiragJain 让我知道有什么令人困惑的地方,我可以澄清一下!
  • 确实是一个明智且合乎逻辑的解决方案!
  • 2 问题:1 您是否因为需要比较值而将对象数组映射到平面数组? 2 是否可以用 .some() 做到这一点
【解决方案5】:

下面的代码是相对于另一个数组过滤一个数组的最简单方法。两个数组都可以在其中包含对象而不是值。

let array1 = [1, 3, 47, 1, 6, 7];
let array2 = [3, 6];
let filteredArray1 = array1.filter(el => array2.includes(el));
console.log(filteredArray1); 

输出:[3, 6]

【讨论】:

  • 这不是过滤。输出是array2。为什么这个答案有 19 票赞成?没有意义。
【解决方案6】:

如果您需要比较对象数组,这适用于所有情况:

let arr = [{ id: 1, title: "title1" },{ id: 2, title: "title2" }]
let brr = [{ id: 2, title: "title2" },{ id: 3, title: "title3" }]

const res = arr.filter(f => brr.some(item => item.id === f.id));
console.log(res);

【讨论】:

    【解决方案7】:

    上述所有解决方案都“有效”,但在性能方面不是最优的,并且都以相同的方式解决问题,即使用Array.prototype.indexOfArray.prototype.includes 在每个点线性搜索所有条目。一个更快的解决方案(在大多数情况下甚至比二进制搜索要快得多)是对数组进行排序并在您继续进行时向前跳过,如下所示。但是,一个缺点是这要求数组中的所有条目都是数字或字符串。然而,在极少数情况下,二分搜索可能比渐进式线性搜索更快。这些情况源于我的渐进式线性搜索的复杂度为 O(2n1+n2)(只有 O (n1+n2) 在更快的 C/C++ 版本中)(其中 n1 是搜索到的数组,n2 是过滤器数组),而二分查找的复杂度为 O(n1 ceil(log2n2)) (ceil = 向上取整 -- 到 ceiling),最后, indexOf 搜索在 O(n1)O(n1n2 之间具有高度可变的复杂性sub>),平均到 O(n1ceil(n2÷2))。因此,平均而言, indexOf 只会在 (n1,n2) 等于 {1 的情况下是最快的,2}{1,3}{x,1|x∈N}。但是,这仍然不是现代硬件的完美代表。 IndexOf 在大多数现代浏览器中进行了最大程度的原生优化,使其非常符合branch prediction 的法律。因此,如果我们对 indexOf 做出与渐进式线性和二进制搜索相同的假设——数组是预排序的——那么,根据链接中列出的统计数据,我们可以预期 IndexOf 的速度大约提高 6 倍,将其复杂度转移到 O(n1÷6)O(n1n2 之间),平均为 O(n1ceil(n27÷12))。最后,请注意,下面的解决方案永远不会与对象一起使用,因为 JavaScript 中的对象无法通过 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
        }
      };
    }
    

    有关使用的二分搜索算法的更多详细信息,请参阅我的另一篇帖子here

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

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

    为了证明速度上的差异,让我们检查一些 JSPerfs。对于filtering an array of 16 elements,二分查找比 indexOf 快大约 17%,而 filterArrayByAnotherArray 比 indexOf 快大约 93%。对于filtering an array of 256 elements,二分查找比 indexOf 快大约 291%,而 filterArrayByAnotherArray 比 indexOf 快大约 353%。对于filtering an array of 4096 elements,二分查找比 indexOf 快大约 2655%,而 filterArrayByAnotherArray 比 indexOf 快大约 4627%。

    反向过滤(如与门)

    上一节提供了获取数组 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;
        });
    }
    

    【讨论】:

    • 感谢您的回答,我相信迟早会对某人有所帮助,即使它应该用于边缘情况(即仅在出现性能问题时)。在所有其他情况下,我建议使用可维护/可读版本。
    • @JackGiffin 我认为可读性意味着普通网络开发人员可以快速阅读和理解,因为当需要更改或简单理解时。很好的解决方案,只是不适用于大多数情况。
    • @JackGiffin 早期优化对于项目来说是最糟糕的事情之一,性能应该普遍应用于编写高效代码的方式,如果足够简单,意味着不要直接编写糟糕的代码,当优化是需要,因为性能不符合要求。所以像你这样的人应该努力优化其他需要这种痴迷技能的项目。希望它有所帮助:)
    • @zardilior 确实有帮助。非常感谢您的建议 zardilior。我会把它铭记在心并采取行动。
    • @JackGiffin 很高兴为您服务
    【解决方案8】:

    您的问题有很多答案,但我没有看到有人使用 lambda 表达式:

    var array = [1,2,3,4];
    var anotherOne = [2,4];
    var filteredArray = array.filter(x => anotherOne.indexOf(x) < 0);
    

    【讨论】:

      【解决方案9】:

      带有对象过滤结果

      [{id:1},{id:2},{id:3},{id:4}].filter(v=>!([{id:2},{id:4}].some(e=>e.id === v.id)))
      

      【讨论】:

        【解决方案10】:

        OA也可以在ES6中实现如下

        ES6:

         const filtered = [1, 2, 3, 4].filter(e => {
            return this.indexOf(e) < 0;
          },[2, 4]);
        

        【讨论】:

        • 在箭头语法之外,这个解决方案在过滤方面有什么 ES6 优势?
        【解决方案11】:

        下面是一个例子

        let firstArray=[1,2,3,4,5];
        let secondArray=[2,3];  
        let filteredArray = firstArray.filter((a) => secondArray.indexOf(a)<0);
        console.log(filteredArray); //above line gives [1,4,5]

        【讨论】:

          【解决方案12】:

          您可以设置过滤器函数来迭代“过滤器数组”。

          var arr = [1, 2, 3 ,4 ,5, 6, 7];
          var filter = [4, 5, 6];
          
          var filtered = arr.filter(
            function(val) {
              for (var i = 0; i < filter.length; i++) {
                if (val == filter[i]) {
                  return false;
                }
              }
              return true;
            }
          ); 
          

          【讨论】:

            【解决方案13】:

            您可以使用过滤器,然后对过滤器函数使用过滤数组的缩减,该数组检查并在找到匹配项时返回 true,然后在返回时反转 (!)。数组中的每个元素都会调用一次过滤器函数。您没有对帖子中函数中的任何元素进行比较。

            var a1 = [1, 2, 3, 4],
              a2 = [2, 3];
            
            var filtered = a1.filter(function(x) {
              return !a2.reduce(function(y, z) {
                return x == y || x == z || y == true;
              })
            });
            
            document.write(filtered);

            【讨论】:

              【解决方案14】:

              var arr1= [1,2,3,4];
              var arr2=[2,4]
              
              function fil(value){
              return value !=arr2[0] &&  value != arr2[1]
              }
              
              document.getElementById("p").innerHTML= arr1.filter(fil)
              <!DOCTYPE html> 
              <html> 
              <head> 
              </head>
              <body>
              <p id="p"></p>

              【讨论】:

              • 谢谢,它可以工作,但我更愿意保留本地范围。 arr2 也有随机数量的元素。
              【解决方案15】:

              function arr(arr1,arr2){
                
                function filt(value){
                  return arr2.indexOf(value) === -1;
                  }
                
                return arr1.filter(filt)
                }
              
              document.getElementById("p").innerHTML = arr([1,2,3,4],[2,4])
              &lt;p id="p"&gt;&lt;/p&gt;

              【讨论】:

                【解决方案16】:

                从另一个包含对象属性的数组中筛选出一个更灵活的数组

                function filterFn(array, diffArray, prop, propDiff) {
                    diffArray = !propDiff ? diffArray : diffArray.map(d => d[propDiff])
                    this.fn = f => diffArray.indexOf(f) === -1
                    if (prop) {
                         return array.map(r => r[prop]).filter(this.fn)
                    } else {
                         return array.filter(this.fn)
                    }
                }
                
                //You can use it like this;
                
                var arr = [];
                
                for (var i = 0; i < 10; i++) {
                    var obj = {}
                    obj.index = i
                    obj.value = Math.pow(2, i)
                    arr.push(obj)
                }
                
                var arr2 = [1, 2, 3, 4, 5]
                
                var sec = [{t:2}, {t:99}, {t:256}, {t:4096}]
                
                var log = console.log.bind(console)
                
                var filtered = filterFn(arr, sec, 'value', 't')
                
                var filtered2 = filterFn(arr2, sec, null, 't')
                
                log(filtered, filtered2)

                【讨论】:

                  【解决方案17】:

                  您可以编写一个通用的 filterByIndex() 函数并利用 TS 中的类型推断来省去回调函数的麻烦:

                  假设您有一个数组 [1,2,3,4],您想要使用 [2,4] 数组中指定的索引进行过滤()。

                  var filtered = [1,2,3,4,].filter(byIndex(element => element, [2,4]))
                  

                  byIndex 函数需要元素函数和一个数组,如下所示:

                  byIndex = (getter: (e:number) => number, arr: number[]) => (x: number) => {
                      var i = getter(x);
                      return arr.indexOf(i); 
                  }
                  

                  结果就是

                  filtered = [1,3]
                  

                  【讨论】:

                    【解决方案18】:

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

                    【讨论】:

                      【解决方案19】:

                      filter函数的最佳描述是https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Array/filter

                      你应该简单的条件函数:

                      function conditionFun(element, index, array) {
                         return element >= 10;
                      }
                      filtered = [12, 5, 8, 130, 44].filter(conditionFun);
                      

                      而且你不能在赋值之前访问变量值

                      【讨论】:

                      • 这个答案只使用一个数组。
                      【解决方案20】:

                      以下示例使用new Set() 创建一个仅包含唯一元素的过滤数组:

                      具有原始数据类型的数组:字符串、数字、布尔值、null、未定义、符号:

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

                      【讨论】:

                        【解决方案21】:

                        当数组中的项目是对象时,您可以这样做。

                        这个想法是使用 map 函数在内部数组中找到只有键的数组

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

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

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2013-02-26
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2019-01-18
                          • 1970-01-01
                          • 1970-01-01
                          • 2018-03-07
                          相关资源
                          最近更新 更多