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

javascript arrays

943840 просмотра

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
Автор: zimbatm Источник Размещён: 17.05.2019 02:49

Ответы (8)


678 плюса

Решение

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

arr.includes(obj);

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

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

РЕДАКТИРОВАТЬ: Это не будет работать на IE6, 7 или 8, хотя. Лучший обходной путь - определить его самостоятельно, если его нет:

  1. Версия Mozilla (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);
      }
    );
    
Автор: Vinko Vrsalovic Размещён: 27.09.2008 03:45

208 плюса

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

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

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

Автор: GerManson Размещён: 27.03.2010 12:37

33 плюса

Во-первых, используйте indexOfJavaScript для браузеров, у которых его еще нет. Например, см. Дополнения к массиву Эрика Арвидссона (также, связанный пост в блоге ). И тогда вы можете использовать, 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 в комментариях, к тестам поиска в массивах . Хотя они довольно грубые, полное расследование должно было бы проверить массивы разных типов, разной длины и найти объекты, которые встречаются в разных местах.

Автор: Daniel James Размещён: 27.09.2008 06:10

11 плюса

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

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

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

Автор: assortedslog Размещён: 27.09.2008 03:50

10 плюса

[] .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
Автор: bortunac Размещён: 24.02.2012 06:11

6 плюса

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

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

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

Автор: PhiLho Размещён: 27.09.2008 04:28

5 плюса

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

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

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

Автор: Paul Dixon Размещён: 27.09.2008 03:51

4 плюса

Надежный способ проверить, является ли объект массивом в 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;
}
Автор: Aaria Carter-Weir Размещён: 17.08.2011 12:57
Вопросы из категории :
32x32