找到一个项目是否在JavaScript数组中的最佳方法?

Best way to find if an item is in a JavaScript array?

本问题已经有最佳答案,请猛点这里访问。

找到对象是否在数组中的最好方法是什么?

这是我知道的最好的方法:

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

include([1,2,3,4], 3); // true
include([1,2,3,4], 6); // undefined


从ecmascript 2016起,您可以使用includes()

1
arr.includes(obj);

如果要支持IE或其他较旧的浏览器:

1
2
3
function include(arr,obj) {
    return (arr.indexOf(obj) != -1);
}

编辑:但这在IE6、7或8上不起作用。最好的解决方法是自己定义它,如果它不存在:

  • Mozilla(ECMA-262)版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
      if (!Array.prototype.indexOf)
      {

           Array.prototype.indexOf = function(searchElement /*, fromIndex */)

        {


       "use strict";

        if (this === void 0 || this === null)
          throw new TypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0)
          return -1;

        var n = 0;
        if (arguments.length > 0)
        {
          n = Number(arguments[1]);
          if (n !== n)
            n = 0;
          else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
            n = (n > 0 || -1) * Math.floor(Math.abs(n));
        }

        if (n >= len)
          return -1;

        var k = n >= 0
              ? n
              : Math.max(len - Math.abs(n), 0);

        for (; k < len; k++)
        {
          if (k in t && t[k] === searchElement)
            return k;
        }
        return -1;
      };

    }
  • 丹尼尔·詹姆斯的版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    if (!Array.prototype.indexOf) {
      Array.prototype.indexOf = function (obj, fromIndex) {
        if (fromIndex == null) {
            fromIndex = 0;
        } else if (fromIndex < 0) {
            fromIndex = Math.max(0, this.length + fromIndex);
        }
        for (var i = fromIndex, j = this.length; i < j; i++) {
            if (this[i] === obj)
                return i;
        }
        return -1;
      };
    }
  • Roosteronacid的版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Array.prototype.hasObject = (
      !Array.indexOf ? function (o)
      {
        var l = this.length + 1;
        while (l -= 1)
        {
            if (this[l - 1] === o)
            {
                return true;
            }
        }
        return false;
      } : function (o)
      {
        return (this.indexOf(o) !== -1);
      }
    );

  • 如果使用jQuery:

    1
    $.inArray(5 + 5, ["8","9","10", 10 +"" ]);

    有关更多信息:HTTP://API.jQueR.COM/jQueR.InAARYA/


    首先,在还没有的浏览器中用JavaScript实现indexOf。例如,请参见Erik Arvidsson的"阵列附加"(以及相关的博客文章)。然后您可以使用indexOf,而不必担心浏览器支持。下面是他的indexOf实现的一个稍微优化的版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (obj, fromIndex) {
            if (fromIndex == null) {
                fromIndex = 0;
            } else if (fromIndex < 0) {
                fromIndex = Math.max(0, this.length + fromIndex);
            }
            for (var i = fromIndex, j = this.length; i < j; i++) {
                if (this[i] === obj)
                    return i;
            }
            return -1;
        };
    }

    它被更改为存储长度,这样就不需要每次迭代都查找它了。但差别不大。不太通用的功能可能更快:

    1
    2
    3
    4
    5
    6
    7
    var include = Array.prototype.indexOf ?
        function(arr, obj) { return arr.indexOf(obj) !== -1; } :
        function(arr, obj) {
            for(var i = -1, j = arr.length; ++i < j;)
                if(arr[i] === obj) return true;
            return false;
        };

    我更喜欢使用标准函数,并且在需要的时候保留这种微优化。但是,如果你热衷于微优化,我将基准中的ROOSTONNONE链接到评论中,以便在数组中进行基准搜索。它们是相当粗糙的,但是,一个完整的调查将测试不同类型,不同长度的阵列,并发现在不同的地方发生的物体。


    如果数组没有排序,那么就没有更好的方法了(除了使用上面提到的indexof,我认为这是一回事)。如果对数组进行排序,则可以执行二进制搜索,其工作方式如下:

  • 选择数组的中间元素。
  • 你要找的元素比你选的元素大吗?如果是这样,就消除了数组的下半部分。如果不是的话,你已经淘汰了上半场。
  • 选择数组其余一半的中间元素,并继续执行步骤2,消除其余一半的数组。最终,您要么找到元素,要么没有数组可供查看。
  • 二进制搜索的运行时间与数组长度的对数成比例,因此它可能比查看每个元素快得多。


    [](OBJ)

    假设执行.indexOf()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Object.defineProperty( Array.prototype,'has',
    {
        value:function(o, flag){
        if (flag === undefined) {
            return this.indexOf(o) !== -1;
        } else {   // only for raw js object
            for(var v in this) {
                if( JSON.stringify(this[v]) === JSON.stringify(o)) return true;
            }
            return false;                      
        },
        // writable:false,
        // enumerable:false
    })

    !!!!不要使用Array.prototype.has=function(){...,因为您将在每个数组中添加一个可枚举的元素,而JS将被破坏。

    1
    2
    3
    4
    5
    6
    //use like          
    [22 ,'a', {prop:'x'}].has(12) // false
    ["a","b"].has("a") //  true

    [1,{a:1}].has({a:1},1) // true
    [1,{a:1}].has({a:1}) // false

    使用第二个arg(flag)强制按值而不是参照进行比较

    比较原始对象

    1
    [o1].has(o2,true) // true if every level value is same

    这取决于你的目的。如果您为Web编程,请避免使用indexOf,它不受Internet Explorer 6的支持(其中很多仍在使用!)或做有条件的使用:

    1
    2
    if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
    else result = customSlowerSearch(yourArray, target);

    indexOf可能是用本机代码编码的,因此它比您在javascript中所能做的任何事情都要快(如果数组合适的话,除了二进制搜索/二分法)。注意:这是一个品味问题,但我会在你的程序结束时做一个return false;,返回一个真正的布尔值……


    以下是一些元知识-如果您想知道如何使用数组,请查看文档-这是Mozilla的数组页面

    https://developer.mozilla.org/en-us/docs/javascript/reference/global_对象/array

    在这里,您将看到在javascript 1.6中添加的indexof的引用。


    在JavaScript中检查对象是否为数组的健壮方法详述如下:

    下面是xa.js框架中的两个函数,我将它们附加到utils = {}容器上。这些应该可以帮助您正确地检测数组。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    var utils = {};

    /**
     * utils.isArray
     *
     * Best guess if object is an array.
     */

    utils.isArray = function(obj) {
         // do an instanceof check first
         if (obj instanceof Array) {
             return true;
         }
         // then check for obvious falses
         if (typeof obj !== 'object') {
             return false;
         }
         if (utils.type(obj) === 'array') {
             return true;
         }
         return false;
     };

    /**
     * utils.type
     *
     * Attempt to ascertain actual object type.
     */

    utils.type = function(obj) {
        if (obj === null || typeof obj === 'undefined') {
            return String (obj);
        }
        return Object.prototype.toString.call(obj)
            .replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase();
    };

    如果要检查对象是否在数组中,我还将包括以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
     * Adding hasOwnProperty method if needed.
     */

    if (typeof Object.prototype.hasOwnProperty !== 'function') {
        Object.prototype.hasOwnProperty = function (prop) {
            var type = utils.type(this);
            type = type.charAt(0).toUpperCase() + type.substr(1);
            return this[prop] !== undefined
                && this[prop] !== window[type].prototype[prop];
        };
    }

    最后,在数组函数中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function in_array (needle, haystack, strict) {
        var key;

        if (strict) {
            for (key in haystack) {
                if (!haystack.hasOwnProperty[key]) continue;

                if (haystack[key] === needle) {
                    return true;
                }
            }
        } else {
            for (key in haystack) {
                if (!haystack.hasOwnProperty[key]) continue;

                if (haystack[key] == needle) {
                    return true;
                }
            }
        }

        return false;
    }