it-swarm.com.ru

Лучший способ узнать, есть ли элемент в массиве JavaScript?

Каков наилучший способ найти объект в массиве?

Это лучший способ, которым я знаю:

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
743
zimbatm

Начиная с ECMAScript 2016 вы можете использовать includes()

arr.includes(obj);

Если вы хотите поддерживать IE или другие старые браузеры:

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

Правка: Это не будет работать на IE6, 7 или 8, хотя. Лучший обходной путь - определить его самостоятельно, если его нет:

  1. Mozilla's (ECMA-262) версия:

      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;
      };
    
    }
    
  2. Даниэль Джеймс версия:

    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;
      };
    }
    
  3. roosteronacid версия:

    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);
      }
    );
    
688
Vinko Vrsalovic

Если вы используете jQuery:

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

Для получения дополнительной информации: http://api.jquery.com/jQuery.inArray/

207
GerManson

Во-первых, внедрите indexOf в JavaScript для браузеров, у которых его еще нет. Например, смотрите Дополнения к массиву Эрика Арвидссона (также связанный пост в блоге ). И тогда вы можете использовать indexOf, не беспокоясь о поддержке браузера. Вот слегка оптимизированная версия его реализации indexOf:

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

Он изменен для хранения длины, поэтому нет необходимости искать его на каждой итерации. Но разница не огромна. Функция менее общего назначения может быть быстрее:

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

Я предпочитаю использовать стандартную функцию и оставлять такую ​​микрооптимизацию, когда это действительно необходимо. Но если вы увлекаетесь микрооптимизацией, я адаптировал тесты , с которыми roosterononacid ссылается в комментариях, к поиск тестов в массивах . Хотя они довольно грубые, полное расследование должно было бы проверить массивы разных типов, разной длины и найти объекты, которые встречаются в разных местах.

33
Daniel James

Если массив не отсортирован, лучшего способа нет (кроме использования вышеупомянутого indexOf, который, я думаю, равносильно тому же). Если массив отсортирован, вы можете выполнить бинарный поиск, который работает следующим образом:

  1. Выберите средний элемент массива.
  2. Является ли элемент, который вы ищете, больше, чем элемент, который вы выбрали? Если это так, вы удалили нижнюю половину массива. Если это не так, вы устранили верхнюю половину.
  3. Выберите средний элемент оставшейся половины массива и продолжайте, как в шаге 2, удаляя половинки оставшегося массива. В конце концов вы либо найдете свой элемент, либо у вас не останется массив для просмотра.

Двоичный поиск выполняется во времени, пропорциональном логарифму длины массива, поэтому он может быть намного быстрее, чем просмотр каждого отдельного элемента.

11
assortedslog

[] .has (obj)

при условии, что .indexOf() реализован

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 не работает.

//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

использование 2-го аргумента (флага) вызывает сравнение по значению вместо ссылки

сравнивая необработанные объекты

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

Это зависит от вашей цели. Если вы программируете для Интернета, избегайте indexOf, это не поддерживается Internet Explorer 6 (многие из них все еще используются!), Или используйте условно:

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

indexOf, вероятно, закодирован в нативном коде, поэтому он работает быстрее, чем все, что вы можете сделать в JavaScript (кроме бинарного поиска/дихотомии, если массив подходит). Примечание: это вопрос вкуса, но я бы сделал return false; в конце вашей процедуры, чтобы вернуть истинное логическое значение ...

6
PhiLho

Вот некоторые мета-знания для вас - если вы хотите знать, что вы можете сделать с Array, проверьте документацию - вот страница Array для Mozilla

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

Там вы увидите ссылку на indexOf, добавленный в Javascript 1.6

5
Paul Dixon

Надежный способ проверить, является ли объект массивом в JavaScript, подробно описан здесь:

Вот две функции из среды xa.js , которые я прикрепляю к utils = {} ‘контейнеру. Это должно помочь вам правильно определять массивы.

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

Если вы хотите проверить, находится ли объект в массиве, я бы также включил этот код:

/**
 * 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];
    };
}

И, наконец, эта функция in_array:

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;
}
4
Aaria Carter-Weir