【问题标题】:How do I check if an array includes a value in JavaScript?如何检查数组是否包含 JavaScript 中的值?
【发布时间】:2021-09-10 07:11:52
【问题描述】:

找出 JavaScript 数组是否包含值的最简洁有效的方法是什么?

这是我知道的唯一方法:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

有没有更好更简洁的方法来实现这一点?

【问题讨论】:

  • 刚刚测试过:你的方式实际上是跨浏览器最快的:jsperf.com/find-element-in-obj-vs-array/2(除了在变量中预先保存a.length)而使用indexOf(如$.inArray)要慢得多
  • 许多人回答说 Array#indexOf 是您最好的选择。但是,如果您想要一些可以正确转换为布尔值的东西,请使用:~[1,2,3].indexOf(4) 将返回 0,其评估结果为 false,而 ~[1,2,3].indexOf(3) 将返回 -3,其评估结果为 true。
  • ~ 不是你想用来转换为布尔值的,因为你需要!。但在这种情况下,你想用 -1 检查是否相等,所以函数可能 endreturn [1,2,3].indexOf(3) === -1; ~ 不是二进制,它会单独反转值的每一位。
  • @Iordvlad [1,2,3].indexOf(4) 实际上是 return -1。正如@mcfedr 所指出的,~bitwise-NOT operator,参见 ES5 11.4.8。问题是,由于-1 的二进制表示仅由 1 组成,它的补码是0,其评估结果为假。任何其他数字的补数都将是非零的,因此是正确的。所以,~ 工作得很好,并且经常与indexOf 结合使用。
  • 标题具有误导性。 [[1,2],[3,4]].includes([3,4]) 在哪里?

标签: javascript arrays algorithm time-complexity javascript-objects


【解决方案1】:

现代浏览器有Array#includes,它完全做到这一点,而is widely supported 除了IE之外的所有人:

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

你也可以使用Array#indexOf,它不那么直接,但对于过时的浏览器不需要polyfill。

console.log(['joe', 'jane', 'mary'].indexOf('jane') &gt;= 0); //true

许多框架也提供类似的方法:

请注意,有些框架将此作为函数实现,而其他框架则将该函数添加到数组原型中。

【讨论】:

  • MooTools 也有 Array.contains 返回一个布尔值,这听起来像是这里的真正问题。
  • prototype 也有 Array.include 返回一个布尔值
  • 如果您使用的是好的浏览器,您可以使用array.indexOf(object) != -1
  • 另外,不要单独使用 indexOf 作为条件,因为第一个元素将返回 0 并被评估为 falsy
  • inArray 是返回元素索引的函数的糟糕名称,如果不存在则返回 -1。我希望返回一个布尔值。
【解决方案2】:

2019 年更新:此答案来自 2008 年(11 岁!),与现代 JS 使用无关。承诺的性能改进是基于当时在浏览器中完成的基准测试。它可能与现代 JS 执行上下文无关。如果您需要一个简单的解决方案,请寻找其他答案。如果您需要最佳性能,请在相关执行环境中进行基准测试。

正如其他人所说,通过数组进行迭代可能是最好的方式,但 has been proven 认为递减的 while 循环是 JavaScript 中最快的迭代方式。所以你可能想重写你的代码如下:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

当然,你也可以扩展 Array 原型:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

现在您可以简单地使用以下内容:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

【讨论】:

【解决方案3】:

indexOf 可能,但它是“ECMA-262 标准的 JavaScript 扩展;因此它可能不会出现在该标准的其他实现中。”

例子:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft does not offer some kind of alternative 对此,但您可以在 Internet Explorer(以及其他不支持 indexOf 的浏览器)中的数组中添加类似的功能,如 quick Google search reveals(例如,@987654324 @)。

【讨论】:

    【解决方案4】:

    最佳答案假定原始类型,但如果您想了解数组是否包含具有某些特征的 objectArray.prototype.some() 是一个优雅的解决方案:

    const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]
    
    items.some(item => item.a === '3')  // returns true
    items.some(item => item.a === '4')  // returns false
    

    它的好处是一旦找到元素就会中止迭代,这样就可以避免不必要的迭代周期。

    此外,它非常适合 if 语句,因为它返回一个布尔值:

    if (items.some(item => item.a === '3')) {
      // do something
    }
    

    * 正如 jamess 在评论中指出的那样,在 2018 年 9 月给出这个答案时,Array.prototype.some() 完全支持:caniuse.com support table

    【讨论】:

      【解决方案5】:

      ECMAScript 7 引入了Array.prototype.includes

      可以这样使用:

      [1, 2, 3].includes(2); // true
      [1, 2, 3].includes(4); // false
      

      它还接受可选的第二个参数fromIndex

      [1, 2, 3].includes(3, 3); // false
      [1, 2, 3].includes(3, -1); // true
      

      与使用Strict Equality ComparisonindexOf 不同,includes 使用SameValueZero 相等算法进行比较。这意味着您可以检测数组是否包含NaN:

      [1, 2, NaN].includes(NaN); // true
      

      也不同于indexOfincludes 不会跳过缺失的索引:

      new Array(5).includes(undefined); // true
      

      目前它仍然是一个草稿,但可以polyfilled 使其适用于所有浏览器。

      【讨论】:

        【解决方案6】:

        假设你已经定义了一个这样的数组:

        const array = [1, 2, 3, 4]
        

        以下是检查其中是否有3 的三种方法。它们都返回truefalse

        Native Array 方法(ES2016 起)(compatibility table)

        array.includes(3) // true
        

        作为自定义 Array 方法(ES2016 之前)

        // Prefixing the method with '_' to avoid name clashes
        Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
        array._includes(3) // true
        

        简单功能

        const includes = (a, v) => a.indexOf(v) !== -1
        includes(array, 3) // true
        

        【讨论】:

        • "~" 是一个运算符,用于对数字进行取整、反转和减 1。 indexOf 如果失败则返回 -1,因此“~”将 -1 变为“0”。使用 ”!!”将数字转换为布尔值 (!!0===false)
        【解决方案7】:

        这是Array.indexOfJavaScript 1.6 compatible 实现:

        if (!Array.indexOf) {
            Array.indexOf = [].indexOf ?
                function(arr, obj, from) {
                    return arr.indexOf(obj, from);
                } :
                function(arr, obj, from) { // (for IE6)
                    var l = arr.length,
                        i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
                    i = i < 0 ? 0 : i;
                    for (; i < l; i++) {
                        if (i in arr && arr[i] === obj) {
                            return i;
                        }
                    }
                    return -1;
                };
        }
        

        【讨论】:

        • 这看起来不错,但有点困惑: * 第 1 行和第 3 行的测试不是等效的吗? * 测试一下原型,如果需要的话,在Array.prototype中加入函数不是更好吗?
        • 它们不是等价的。 [].indexOfArray.prototype.indexOf 的简写。我们偏执的 Javascript 程序员不惜一切代价避免扩展原生原型。
        • [].indexOf不是创建一个新数组然后访问indexOf,而Array.prototype.indexOf只是直接访问原型?
        • @alex 是 [].indexOf === Array.prototype.indexOf(在 FireBug 中尝试),但反过来 [].indexOf !== Array.indexOf
        【解决方案8】:

        用途:

        function isInArray(array, search)
        {
            return array.indexOf(search) >= 0;
        }
        
        // Usage
        if(isInArray(my_array, "my_value"))
        {
            //...
        }
        

        【讨论】:

        • x ? true : false 通常是多余的。它就在这里。
        • @minitech 为什么说它是多余的?
        • array.indexOf(search) &gt;= 0 已经是一个布尔值。只需return array.indexOf(search) &gt;= 0
        • @minitech 非常感谢!其实我不知道这样的建筑可以退货。直到一些新的东西。
        【解决方案9】:

        扩展 JavaScript Array 对象是一个非常糟糕的主意,因为您将新属性(您的自定义方法)引入到 for-in 循环中,这可能会破坏现有脚本。几年前,Prototype 库的作者不得不重新设计他们的库实现以删除这种东西。

        如果您不需要担心与页面上运行的其他 JavaScript 的兼容性,那就去吧,否则,我会推荐更笨拙但更安全的独立函数解决方案。

        【讨论】:

        • 我不同意。正是出于这个原因,for-in 循环不应该用于数组。使用流行的 js 库之一时,使用 for-in 循环会中断
        【解决方案10】:

        性能

        今天 2020.01.07 我在 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 上针对 15 个选定的解决方案在 MacOs HighSierra 10.13.6 上执行测试。结论

        • 基于JSONSet 和令人惊讶的find (K,N,O) 的解决方案在所有浏览器上都是最慢的
        • es6 includes (F) 仅在 chrome 上速度很快
        • 基于 for (C,D) 和 indexOf (G,H) 的解决方案在小型和大型阵列上的所有浏览器上都非常快,因此它们可能是高效解决方案的最佳选择
        • 在循环期间索引减少的解决方案,(B)可能因为CPU cache works的方式而变慢。
        • 当搜索的元素位于数组长度的 66% 位置时,我还对大数组运行测试,并且基于 for (C,D,E) 的解决方案给出了类似的结果(~630 ops/sec - 但 E 开启safari 和 firefox 比 C 和 D 慢 10-20%)

        结果

        详情

        我执行了 2 个测试用例:包含 10 个元素的数组和包含 100 万个元素的数组。在这两种情况下,我们都将搜索到的元素放在数组中间。

        let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')}  's7'-${f(arr,'s7')}  6-${f(arr,6)} 's3'-${f(arr,'s3')}`)
        
        let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
        //arr = new Array(1000000).fill(123); arr[500000]=7;
        
        function A(a, val) {
            var i = -1;
            var n = a.length;
            while (i++<n) {
               if (a[i] === val) {
                   return true;
               }
            }
            return false;
        }
        
        function B(a, val) {
            var i = a.length;
            while (i--) {
               if (a[i] === val) {
                   return true;
               }
            }
            return false;
        }
        
        function C(a, val) {
            for (var i = 0; i < a.length; i++) {
                if (a[i] === val) return true;
            }
            return false;
        }
        
        function D(a,val)
        {
            var len = a.length;
            for(var i = 0 ; i < len;i++)
            {
                if(a[i] === val) return true;
            }
            return false;
        } 
        
        function E(a, val){  
          var n = a.length-1;
          var t = n/2;
          for (var i = 0; i <= t; i++) {
                if (a[i] === val || a[n-i] === val) return true;
          }
          return false;
        }
        
        function F(a,val) {
        	return a.includes(val);
        }
        
        function G(a,val) {
        	return a.indexOf(val)>=0;
        }
        
        function H(a,val) {
        	return !!~a.indexOf(val);
        }
        
        function I(a, val) {
          return a.findIndex(x=> x==val)>=0;
        }
        
        function J(a,val) {
        	return a.some(x=> x===val);
        }
        
        function K(a, val) {
          const s = JSON.stringify(val);
          return a.some(x => JSON.stringify(x) === s);
        }
        
        function L(a,val) {
        	return !a.every(x=> x!==val);
        }
        
        function M(a, val) {
          return !!a.find(x=> x==val);
        }
        
        function N(a,val) {
        	return a.filter(x=>x===val).length > 0;
        }
        
        function O(a, val) {
          return new Set(a).has(val);
        }
        
        log('A',A);
        log('B',B);
        log('C',C);
        log('D',D);
        log('E',E);
        log('F',F);
        log('G',G);
        log('H',H);
        log('I',I);
        log('J',J);
        log('K',K);
        log('L',L);
        log('M',M);
        log('N',N);
        log('O',O);
        This shippet only presents functions used in performance tests - it not perform tests itself!

        小数组 - 10 个元素

        你可以在你的机器上进行测试HERE

        大数组 - 1.000.000 个元素

        你可以在你的机器上进行测试HERE

        【讨论】:

          【解决方案11】:

          单线:

          function contains(arr, x) {
              return arr.filter(function(elem) { return elem == x }).length > 0;
          }
          

          【讨论】:

          • array.filter(e=&gt;e==x).length &gt; 0 等价于array.some(e=&gt;e==x)some 更高效
          【解决方案12】:

          想一想,如果您要多次调用此调用,则使用 关联数组 Map 使用散列函数进行查找会大大提高效率。

          https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

          【讨论】:

            【解决方案13】:

            我使用以下:

            Array.prototype.contains = function (v) {
                return this.indexOf(v) > -1;
            }
            
            var a = [ 'foo', 'bar' ];
            
            a.contains('foo'); // true
            a.contains('fox'); // false
            

            【讨论】:

              【解决方案14】:
              function contains(a, obj) {
                  return a.some(function(element){return element == obj;})
              }
              

              Array.prototype.some() 在第 5 版中被添加到 ECMA-262 标准中

              【讨论】:

              • 如果使用 es6 则可以缩短为 contains = (a, obj) =&gt; a.some((element) =&gt; element === obj))
              • ECMAScript 5 开始,甚至 IE9 也支持 Array.prototype.some()
              【解决方案15】:

              如果您使用 JavaScript 1.6 或更高版本(Firefox 1.5 或更高版本),您可以使用Array.indexOf。否则,我认为您最终会得到与原始代码相似的内容。

              【讨论】:

                【解决方案16】:

                希望更快的双向indexOf / lastIndexOf 替代方案

                2015

                虽然includes这个新方法很不错,但目前支持基本为零。

                我一直在想办法替换缓慢的 indexOf/lastIndexOf 函数。

                已经找到了一种高效的方法,查看最热门的答案。我选择了@Damir Zekic 发布的contains 函数,它应该是最快的。但它也指出,基准来自 2008 年,因此已经过时。

                我也更喜欢while 而不是for,但由于没有特定原因,我用for循环结束了编写函数。也可以通过while -- 完成。

                我很好奇如果我在执行过程中检查数组的两侧,迭代是否会慢得多。显然没有,所以这个函数比投票最多的函数快两倍左右。显然它也比原生更快。这是在真实世界环境中,您永远不知道要搜索的值是在数组的开头还是结尾。

                当您知道您只是推送了一个带有值的数组时,使用 lastIndexOf 可能仍然是最好的解决方案,但如果您必须遍历大型数组并且结果可能无处不在,这可能是一个让事情变得更快的可靠解决方案。

                双向 indexOf/lastIndexOf

                function bidirectionalIndexOf(a, b, c, d, e){
                  for(c=a.length,d=c*1; c--; ){
                    if(a[c]==b) return c; //or this[c]===b
                    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
                  }
                  return -1
                }
                
                //Usage
                bidirectionalIndexOf(array,'value');
                

                性能测试

                http://jsperf.com/bidirectionalindexof

                作为测试,我创建了一个包含 10 万个条目的数组。

                三个查询:数组的开头、中间和结尾。

                我希望你也觉得这很有趣并测试性能。

                注意:如您所见,我略微修改了 contains 函数以反映 indexOf 和 lastIndexOf 输出(所以基本上 trueindexfalse-1)。这不应该伤害它。

                数组原型变体

                Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
                  for(c=this.length,d=c*1; c--; ){
                    if(this[c]==b) return c; //or this[c]===b
                    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
                  }
                  return -1
                },writable:false, enumerable:false});
                
                // Usage
                array.bidirectionalIndexOf('value');
                

                该函数也可以很容易地修改为返回真或假,甚至是对象、字符串或其他任何东西。

                这里是while 变体:

                function bidirectionalIndexOf(a, b, c, d){
                  c=a.length; d=c-1;
                  while(c--){
                    if(b===a[c]) return c;
                    if(b===a[d-c]) return d-c;
                  }
                  return c
                }
                
                // Usage
                bidirectionalIndexOf(array,'value');
                

                这怎么可能?

                我认为获取数组中反射索引的简单计算非常简单,比实际循环迭代快两倍。

                这是一个复杂的示例,每次迭代执行 3 次检查,但这只有在计算时间较长的情况下才有可能,这会导致代码变慢。

                http://jsperf.com/bidirectionalindexof/2

                【讨论】:

                  【解决方案17】:
                  function inArray(elem,array)
                  {
                      var len = array.length;
                      for(var i = 0 ; i < len;i++)
                      {
                          if(array[i] == elem){return i;}
                      }
                      return -1;
                  } 
                  

                  如果找到则返回数组索引,如果未找到则返回 -1

                  【讨论】:

                    【解决方案18】:

                    我们使用这个 sn-p(适用于对象、数组、字符串):

                    /*
                     * @function
                     * @name Object.prototype.inArray
                     * @description Extend Object prototype within inArray function
                     *
                     * @param {mix}    needle       - Search-able needle
                     * @param {bool}   searchInKey  - Search needle in keys?
                     *
                     */
                    Object.defineProperty(Object.prototype, 'inArray',{
                        value: function(needle, searchInKey){
                    
                            var object = this;
                    
                            if( Object.prototype.toString.call(needle) === '[object Object]' || 
                                Object.prototype.toString.call(needle) === '[object Array]'){
                                needle = JSON.stringify(needle);
                            }
                    
                            return Object.keys(object).some(function(key){
                    
                                var value = object[key];
                    
                                if( Object.prototype.toString.call(value) === '[object Object]' || 
                                    Object.prototype.toString.call(value) === '[object Array]'){
                                    value = JSON.stringify(value);
                                }
                    
                                if(searchInKey){
                                    if(value === needle || key === needle){
                                    return true;
                                    }
                                }else{
                                    if(value === needle){
                                        return true;
                                    }
                                }
                            });
                        },
                        writable: true,
                        configurable: true,
                        enumerable: false
                    });
                    

                    用法:

                    var a = {one: "first", two: "second", foo: {three: "third"}};
                    a.inArray("first");          //true
                    a.inArray("foo");            //false
                    a.inArray("foo", true);      //true - search by keys
                    a.inArray({three: "third"}); //true
                    
                    var b = ["one", "two", "three", "four", {foo: 'val'}];
                    b.inArray("one");         //true
                    b.inArray('foo');         //false
                    b.inArray({foo: 'val'})   //true
                    b.inArray("{foo: 'val'}") //false
                    
                    var c = "String";
                    c.inArray("S");        //true
                    c.inArray("s");        //false
                    c.inArray("2", true);  //true
                    c.inArray("20", true); //false
                    

                    【讨论】:

                      【解决方案19】:

                      如果您反复检查数组中是否存在对象,您可能应该查看

                      1. 通过在数组中执行insertion sort 始终保持数组排序(将新对象放在正确的位置)
                      2. 将更新对象作为删除+排序插入操作和
                      3. 在您的contains(a, obj) 中使用binary search 查找。

                      【讨论】:

                      • 或者如果可能的话,完全停止使用数组,而是使用对象作为字典,正如 MattMcKnight 和 ninjagecko 所建议的那样。
                      【解决方案20】:

                      适用于所有现代浏览器的解决方案:

                      function contains(arr, obj) {
                        const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
                        return arr.some(item => JSON.stringify(item) === stringifiedObj);
                      }
                      

                      用法:

                      contains([{a: 1}, {a: 2}], {a: 1}); // true
                      

                      IE6+解决方案:

                      function contains(arr, obj) {
                        var stringifiedObj = JSON.stringify(obj)
                        return arr.some(function (item) {
                          return JSON.stringify(item) === stringifiedObj;
                        });
                      }
                      
                      // .some polyfill, not needed for IE9+
                      if (!('some' in Array.prototype)) {
                        Array.prototype.some = function (tester, that /*opt*/) {
                          for (var i = 0, n = this.length; i < n; i++) {
                            if (i in this && tester.call(that, this[i], i, this)) return true;
                          } return false;
                        };
                      }
                      

                      用法:

                      contains([{a: 1}, {a: 2}], {a: 1}); // true
                      

                      为什么要使用JSON.stringify

                      Array.indexOfArray.includes(以及此处的大多数答案)仅按引用而不是按值进行比较。

                      [{a: 1}, {a: 2}].includes({a: 1});
                      // false, because {a: 1} is a new object
                      

                      奖金

                      未优化的 ES6 单行:

                      [{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
                      // true
                      

                      注意: 如果键的顺序相同,按值比较对象会更好,所以为了安全起见,您可以先使用这样的包对键进行排序:https://www.npmjs.com/package/sort-keys


                      使用性能优化更新了contains 函数。感谢itinance 指出。

                      【讨论】:

                        【解决方案21】:

                        使用 lodash 的 some 函数。

                        简洁、准确,并具有出色的跨平台支持。

                        接受的答案甚至不符合要求。

                        要求:推荐最简洁有效的方法来判断一个 JavaScript 数组是否包含一个对象。

                        接受的答案:

                        $.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
                        > -1
                        

                        我的建议:

                        _.some([{'a': 1}, {'b': 2}], {'b': 2})
                        > true
                        

                        注意事项:

                        $.inArray 可以很好地确定标量数组中是否存在 scalar 值...

                        $.inArray(2, [1,2])
                        > 1
                        

                        ...但问题显然要求一种有效的方法来确定 object 是否包含在数组中。

                        为了同时处理标量和对象,您可以这样做:

                        (_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
                        

                        【讨论】:

                          【解决方案22】:

                          ECMAScript 6 在 find 上有一个优雅的提议。

                          find 方法对每个元素执行一次回调函数 存在于数组中,直到找到回调返回 true 的位置 价值。如果找到这样的元素,find 立即返回值 那个元素。否则,find 返回 undefined。回调是 仅对具有赋值的数组索引调用;它 不会为已删除或从未删除过的索引调用 被赋值。

                          这是上面的MDN documentation

                          查找功能是这样工作的。

                          function isPrime(element, index, array) {
                              var start = 2;
                              while (start <= Math.sqrt(element)) {
                                  if (element % start++ < 1) return false;
                              }
                              return (element > 1);
                          }
                          
                          console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
                          console.log( [4, 5, 8, 12].find(isPrime) ); // 5
                          

                          您可以通过 defining the function 在 ECMAScript 5 及更低版本中使用它。

                          if (!Array.prototype.find) {
                            Object.defineProperty(Array.prototype, 'find', {
                              enumerable: false,
                              configurable: true,
                              writable: true,
                              value: function(predicate) {
                                if (this == null) {
                                  throw new TypeError('Array.prototype.find called on null or undefined');
                                }
                                if (typeof predicate !== 'function') {
                                  throw new TypeError('predicate must be a function');
                                }
                                var list = Object(this);
                                var length = list.length >>> 0;
                                var thisArg = arguments[1];
                                var value;
                          
                                for (var i = 0; i < length; i++) {
                                  if (i in list) {
                                    value = list[i];
                                    if (predicate.call(thisArg, value, i, list)) {
                                      return value;
                                    }
                                  }
                                }
                                return undefined;
                              }
                            });
                          }
                          
                          【解决方案23】:

                          虽然array.indexOf(x)!=-1 是执行此操作的最简洁的方法(并且已被非 Internet Explorer 浏览器支持十多年...),但它不是 O(1),而是 O(N),这太可怕了。如果您的数组不会改变,您可以将数组转换为哈希表,然后执行table[x]!==undefined===undefined

                          Array.prototype.toTable = function() {
                              var t = {};
                              this.forEach(function(x){t[x]=true});
                              return t;
                          }
                          

                          演示:

                          var toRemove = [2,4].toTable();
                          [1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
                          

                          (不幸的是,虽然您可以创建一个 Array.prototype.contains 来“冻结”一个数组并将哈希表存储在 this._cache 中的两行中,但如果您选择稍后编辑您的数组,这将给出错误的结果。JavaScript 有没有足够的钩子让你保持这种状态,不像 Python。)

                          【讨论】:

                            【解决方案24】:

                            可以使用Set,它具有“has()”方法:

                            function contains(arr, obj) {
                                  var proxy = new Set(arr);
                                  if (proxy.has(obj))
                                    return true;
                                  else
                                    return false;
                                }
                            
                                var arr = ['Happy', 'New', 'Year'];
                                console.log(contains(arr, 'Happy'));

                            【讨论】:

                            • 我认为return proxy.has(obj) 比这里有 if-else 语句的两行要干净得多
                            • function contains(arr, obj) { return new Set(arr).has(obj); }
                            【解决方案25】:

                            此要求的简单解决方案是使用find()

                            如果你有如下的对象数组,

                            var users = [{id: "101", name: "Choose one..."},
                            {id: "102", name: "shilpa"},
                            {id: "103", name: "anita"},
                            {id: "104", name: "admin"},
                            {id: "105", name: "user"}];
                            

                            然后您可以检查具有您的值的对象是否已经存在:

                            let data = users.find(object => object['id'] === '104');
                            

                            如果数据为空则没有管理员,否则它将返回现有对象,如:

                            {id: "104", name: "admin"}
                            

                            然后你可以在数组中找到那个对象的索引,并使用代码替换该对象:

                            let indexToUpdate = users.indexOf(data);
                            let newObject = {id: "104", name: "customer"};
                            users[indexToUpdate] = newObject;//your new object
                            console.log(users);
                            

                            您将获得如下价值:

                            [{id: "101", name: "Choose one..."},
                            {id: "102", name: "shilpa"},
                            {id: "103", name: "anita"},
                            {id: "104", name: "customer"},
                            {id: "105", name: "user"}];
                            

                            【讨论】:

                              【解决方案26】:

                              用途:

                              var myArray = ['yellow', 'orange', 'red'] ;
                              
                              alert(!!~myArray.indexOf('red')); //true
                              

                              Demo

                              要确切了解tilde ~ 在这一点上做了什么,请参考这个问题What does a tilde do when it precedes an expression?

                              【讨论】:

                              • 这个已经发过year and half ago 不用重复了。
                              • 其实还没发过。不是作为答案,而是作为对答案的评论,即使这样也不是清晰简洁。感谢您发布它,米娜加布里埃尔。
                              【解决方案27】:

                              好的,您只需优化您的代码即可获得结果!

                              有很多方法可以做到这一点,它们更清洁、更好,但我只是想得到你的模式并使用JSON.stringify 应用到它,只需在你的情况下做这样的事情:

                              function contains(a, obj) {
                                  for (var i = 0; i < a.length; i++) {
                                      if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
                                          return true;
                                      }
                                  }
                                  return false;
                              }
                              

                              【讨论】:

                              • 后期说明:这不适用于contains([{ a: 1, b: 2 }], { b: 2, a: 1 }),因为字符串化的对象保持属性的顺序。
                              【解决方案28】:

                              惊讶于这个问题仍然没有添加最新的语法,增加了我的 2 美分。

                              假设我们有一个对象数组 arrObj,我们想在其中搜索 obj。

                              Array.prototype.indexOf ->(返回index或-1)通常用于查找数组中元素的索引。 这也可以用于搜索对象,但仅在您传递对同一对象的引用时才有效。

                              let obj = { name: 'Sumer', age: 36 };
                              let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
                              
                              
                              console.log(arrObj.indexOf(obj));// 0
                              console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
                              
                              console.log([1, 3, 5, 2].indexOf(2)); //3
                              

                              Array.prototype.includes ->(返回truefalse

                              console.log(arrObj.includes(obj));  //true
                              console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
                              
                              console.log([1, 3, 5, 2].includes(2)); //true
                              

                              Array.prototype.find ->(接受回调,返回第一个在 CB 中返回 true 的 value/object)。

                              console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
                              console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
                              
                              console.log([1, 3, 5, 2].find(e => e > 2)); //3
                              

                              Array.prototype.findIndex ->(接受回调,返回 CB 中返回 true 的第一个值/对象的 index)。

                              console.log(arrObj.findIndex(e => e.age > 40));  //1
                              console.log(arrObj.findIndex(e => e.age > 40)); //1
                              
                              console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
                              

                              由于 find 和 findIndex 接受回调,我们可以通过创造性地设置 true 条件从数组中获取任何对象(即使我们没有引用)。

                              【讨论】:

                                【解决方案29】:

                                绝不是最好的,但我只是在发挥创造力并添加到曲目中。

                                不要使用这个

                                Object.defineProperty(Array.prototype, 'exists', {
                                  value: function(element, index) {
                                
                                    var index = index || 0
                                
                                    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
                                  }
                                })
                                
                                
                                // Outputs 1
                                console.log(['one', 'two'].exists('two'));
                                
                                // Outputs -1
                                console.log(['one', 'two'].exists('three'));
                                
                                console.log(['one', 'two', 'three', 'four'].exists('four'));

                                【讨论】:

                                • 如果不是这个你应该用什么?
                                • @bryc 可能是公认的解决方案,或者来自这里的其他解决方案。如果你不太关心性能,那么你可以使用这个
                                【解决方案30】:

                                它有一个参数:一个对象数组。数组中的每个对象都有两个整数属性,分别用 x 和 y 表示。该函数必须返回数组中满足numbers.x == numbers.y的所有此类对象的计数

                                var numbers = [ { x: 1, y: 1 },
                                                { x: 2, y: 3 },
                                                { x: 3, y: 3 },
                                                { x: 3, y: 4 },
                                                { x: 4, y: 5 } ];
                                var count = 0; 
                                var n = numbers.length;
                                for (var i =0;i<n;i++)
                                {
                                  if(numbers[i].x==numbers[i].y)
                                    {count+=1;}
                                }
                                
                                alert(count);

                                【讨论】:

                                • 你会如何将 x 的值与下一个项目的 x 值进行比较?这不起作用:for (var i = 0; i &lt; n; i++) { if (numbers[i].x == (numbers[i] + 1).x) { count += 1; } }
                                猜你喜欢
                                • 1970-01-01
                                相关资源
                                最近更新 更多