【问题标题】:Check if an element is present in an array [duplicate]检查数组中是否存在元素[重复]
【发布时间】:2011-11-14 17:56:11
【问题描述】:

我现在用来检查的函数如下:

function inArray(needle,haystack)
{
    var count=haystack.length;
    for(var i=0;i<count;i++)
    {
        if(haystack[i]===needle){return true;}
    }
    return false;
}

它有效。我正在寻找的是是否有更好的方法来做到这一点。

【问题讨论】:

  • 对我来说看起来不错。当然,如果您的数组已排序,则可以改为进行二进制搜索。或者,如果数组中的每个值始终是唯一的,您可以使用基于地图的方法。
  • == 运算符?你真的想明确地允许类型强制吗?当然不是。因此,请改用=== 运算符。
  • 在循环之前声明count 是明智之举。您也可以将这两行替换为 for(var i=haystack.length; i--;)
  • 对于数字,也可以使用in 运算符(例如(5 in array)。它可能比其他选项更快,但不适用于字符串或对象或任何其他非数字。

标签: javascript arrays


【解决方案1】:

只需使用indexOf:

haystack.indexOf(needle) >= 0

如果你想支持旧的 Internet Explorer (include your current code as a workaround though。

除非您的列表已排序,否则您需要将每个值与针进行比较。因此,您的解决方案和indexOf 都必须平均执行n/2 比较。但是,由于indexOf 是一种内置方法,它可能会使用额外的优化,并且在实践中会稍微快一些。请注意,除非您的应用程序在列表中搜索非常频繁(例如每秒 1000 次)或列表很大(例如 10 万个条目),否则速度差异并不重要。

【讨论】:

  • Array.prototype.indexOf 没有在 IE8 中实现。
  • 在 IE 中不支持(可能只在 9 中)stackoverflow.com/questions/1744310/…
  • 这在页面上有说明,但作为答案的一部分值得一提:indexOf 是 JavaScript 的一个相对较新的添加,在 9.0 之前的 IE 版本中不支持。同样值得注意的是,indexOf 仍然是 O(n),所以如果 OP 在速度/性能方面意味着“更好”,这实际上不会更好,只是更短。
  • @Tomalak Geret'kal 没错,尽管争论很简单。添加了一段关于性能的段落,以防性能是 OP 对better 的含义。
  • @Francisc - 那么您可以尝试基于地图的方法。那么你的inArray() 实现可以像return haystack[needle] != undefined; 一样简单。
【解决方案2】:

代码:

function isInArray(value, array) {
  return array.indexOf(value) > -1;
}

执行:

isInArray(1, [1,2,3]); // true

更新(2017 年):

在遵循 ECMAScript 2016 (ES7) 标准的现代浏览器中,您可以使用函数Array.prototype.includes,这样可以更轻松地检查数组中是否存在项目:

const array = [1, 2, 3];
const value = 1;
const isInArray = array.includes(value);
console.log(isInArray); // true

【讨论】:

  • !==-1 [额外字符]
  • indexOf 在 IE 浏览器中无法正常工作。
  • @totaldesign 不小心,你的意思是它在IE中不小心工作? :D
  • 在节点 4.4.7 中工作
  • 据我所知,ES2016(包括数组的包含方法)是 ECMAScript 的第七版。 6. 版本是 ES 2015 并且不包含“包含”。请纠正。 en.wikipedia.org/wiki/ECMAScript#7th_Edition_-_ECMAScript_2016
【解决方案3】:

您可以使用 underscore.js 库中的 _contains 函数来实现:

if (_.contains(haystack, needle)) {
  console.log("Needle found.");
};

【讨论】:

  • 下划线库只是为了这个?
  • 不一定,因为开发者可能已经在他们的应用中使用 Underscore 来实现其他功能。使用下划线是众多解决方案中的一种。
【解决方案4】:

在 lodash 中,您可以使用 _.includes(它也是 _.contains 的别名)

你可以搜索整个数组:

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

您可以从起始索引开始搜索数组:

_.includes([1, 2, 3], 1, 1);  // false (begins search at index 1)

搜索一个字符串:

_.includes('pebbles', 'eb');  // true (string contains eb)

也适用于检查简单的对象数组:

_.includes({ 'user': 'fred', 'age': 40 }, 'fred');    // true
_.includes({ 'user': 'fred', 'age': false }, false);  // true

关于最后一种情况需要注意的一点是,它适用于字符串、数字和布尔值等原语,但不能搜索数组或对象

_.includes({ 'user': 'fred', 'age': {} }, {});   // false
_.includes({ 'user': [1,2,3], 'age': {} }, 3);   // false

【讨论】:

    【解决方案5】:

    单行代码.. 将返回真或假

    !!(arr.indexOf("val")+1)
    

    【讨论】:

    • bc 每个人都喜欢波浪号 !!~arr.indexOf("val")
    • 或者只使用~arr.indexOf("val")。 0 = 虚假,其他数字 = 真实
    • uhhh, 0 应该是真的,因为它是作为数组中的第一个元素找到的?
    • 如果您必须迎合 IE11 的最佳解决方案。
    【解决方案6】:

    从 ECMAScript6 开始,可以使用 Set :

    var myArray = ['A', 'B', 'C'];
    var mySet = new Set(myArray);
    var hasB = mySet.has('B'); // true
    var hasZ = mySet.has('Z'); // false
    

    【讨论】:

      【解决方案7】:

      ECMAScript 2016 为数组合并了一个 includes() 方法,专门解决了这个问题,因此现在是首选方法。

      [1, 2, 3].includes(2);     // true
      [1, 2, 3].includes(4);     // false
      [1, 2, 3].includes(1, 2);  // false (second parameter is the index position in this array at which to begin searching)
      

      截至 2018 年 7 月,has been implemented 几乎在所有主要 浏览器中都可用,如果您需要支持旧版浏览器,polyfill 可用。

      编辑:请注意,如果数组中的项目是对象,则返回 false。这是因为相似的对象在 JavaScript 中是两个不同的对象。

      【讨论】:

      • 什么是 polyfill?
      • @nirvanaswap 一个 polyfill 是一个脚本,你可以使用它来确保任何浏览器都可以实现你正在使用的东西。在这种情况下,您将添加一个检查if ("includes" in Array.prototype) 的脚本,如果没有,则实现它(例如,使用Benny's answer 之类的解决方案)。 MDN docs(也链接到此答案)实际上为您提供了一个。
      • 我像下面这样使用它,并且工作正常。并且不要推送重复值。非常感谢!! this.state.UpdatedfriendList.includes(s.valueKey)===false? this.state.UpdatedfriendList.push(s.valueKey):'';
      • @PrithiviRaj 这将是线性时间,因此性能影响将与数组大小成正比。
      • 使用广泛支持的myArray.indexOf(myVal) &gt; -1 是一样的,但更安全
      【解决方案8】:

      我在 Google Chrome 52 上对其进行了多次基准测试,但您可以随意将其复制粘贴到任何其他浏览器的控制台中。


      ~ 1500 ms,包括(当我使用polyfill 时~ 2700 ms)

      var array = [0,1,2,3,4,5,6,7,8,9]; 
      var result = 0;
      
      var start = new Date().getTime();
      for(var i = 0; i < 10000000; i++)
      {
        if(array.includes("test") === true){ result++; }
      }
      console.log(new Date().getTime() - start);
      

      ~ 1050 毫秒,indexOf

      var array = [0,1,2,3,4,5,6,7,8,9]; 
      var result = 0;
      
      var start = new Date().getTime();
      for(var i = 0; i < 10000000; i++)
      {
        if(array.indexOf("test") > -1){ result++; }
      }
      console.log(new Date().getTime() - start);
      

      ~ 650 毫秒,自定义函数

      function inArray(target, array)
      {
      
      /* Caching array.length doesn't increase the performance of the for loop on V8 (and probably on most of other major engines) */
      
        for(var i = 0; i < array.length; i++) 
        {
          if(array[i] === target)
          {
            return true;
          }
        }
      
        return false; 
      }
      
      var array = [0,1,2,3,4,5,6,7,8,9]; 
      var result = 0;
      
      var start = new Date().getTime();
      for(var i = 0; i < 10000000; i++)
      {
        if(inArray("test", array) === true){ result++; }
      }
      console.log(new Date().getTime() - start);
      

      【讨论】:

      • ~ 950 / 750 / 650 在我的笔记本电脑上。我刚刚将数组更改为 ['df','ff',2,3,4,5,6,333,8,9] 并得到了 ~ 950 / 900 / 3150
      【解决方案9】:

      您可以使用indexOf,但在最新版本的 Internet Explorer 中无法正常工作。 代码:

      function isInArray(value, array) {
        return array.indexOf(value) > -1;
      }
      

      执行:

      isInArray(1, [1,2,3]); // true
      

      我建议你使用以下代码:

      function inArray(needle, haystack) {
       var length = haystack.length;
       for (var i = 0; i < length; i++) {
       if (haystack[i] == needle)
        return true;
       }
       return false;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-12-31
        • 2011-06-15
        • 1970-01-01
        • 2011-06-03
        • 2014-02-17
        • 1970-01-01
        相关资源
        最近更新 更多