Как проверить, содержит ли массив объект в JavaScript? - PullRequest
3588 голосов
/ 26 октября 2008

Какой самый краткий и эффективный способ узнать, содержит ли массив JavaScript объект?

Это единственный способ, которым я знаю:

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

Есть ли лучший и более краткий способ сделать это?

Это очень тесно связано с вопросом переполнения стека Лучший способ найти элемент в массиве JavaScript? , который обращается к поиску объектов в массиве с использованием indexOf.

Ответы [ 46 ]

4007 голосов
/ 24 сентября 2009

Текущие браузеры имеют Array#includes, что делает точно , широко поддерживается и имеет polyfill для старых браузеров .

> ['joe', 'jane', 'mary'].includes('jane');
true 

Вы также можете использовать Array#indexOf, который менее прямой, но не требует Polyfills для устаревших браузеров.

jQuery предлагает $.inArray, что функционально эквивалентно Array#indexOf.

underscore.js , библиотека утилит JavaScript, предлагает _.contains(list, value), псевдоним _.include(list, value), оба из которых внутри используют indexOf , если передан JavaScript массив.

Некоторые другие фреймворки предлагают похожие методы:

Обратите внимание, что некоторые платформы реализуют это как функцию, в то время как другие добавляют функцию в прототип массива.

380 голосов
/ 26 октября 2008

Обновление: Как @orip упоминает в комментариях, связанный тест был сделан в 2008 году, поэтому результаты могут быть неактуальными для современных браузеров. Тем не менее, вам, вероятно, понадобится это для поддержки не современных браузеров, и они, вероятно, с тех пор не обновлялись. Всегда проверяйте себя.

Как уже говорили другие, итерация по массиву, вероятно, является лучшим способом, но было доказано , что убывающий цикл 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
177 голосов
/ 26 октября 2008

indexOf возможно, но это «расширение JavaScript к стандарту ECMA-262; как таковое оно может отсутствовать в других реализациях стандарта».

Пример:

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

AFAICS Microsoft не предлагает какую-то альтернативу , но вы можете добавить аналогичные функции для массивов в Internet Explorer (и других браузерах, которые не поддерживают indexOf ) если вы хотите, то как быстрый поиск Google показывает (например, этот ).

143 голосов
/ 01 января 2015

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

В отличие от indexOf, который использует Сравнение строгого равенства , includes сравнивает, используя SameValueZero алгоритм равенства. Это означает, что вы можете определить, содержит ли массив NaN:

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

Также в отличие от indexOf, includes не пропускает пропущенные индексы:

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

В настоящее время это все еще черновик, но его можно заполнить , чтобы он работал во всех браузерах.

102 голосов
/ 24 марта 2012

b - это значение, а a - это массив. Возвращает true или false:

function(a, b) {
    return a.indexOf(b) != -1
}
74 голосов
/ 18 июля 2014

Ответы верхнего уровня предполагают примитивные типы, но если вы хотите узнать, содержит ли массив объект с некоторой чертой, Array.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 года, Array.prototype.some() полностью поддерживается: таблица поддержки caniuse.com

71 голосов
/ 27 октября 2008

Вот JavaScript 1.6 совместимый реализация Array.indexOf:

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;
        };
}
50 голосов
/ 13 сентября 2013

Использование:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
42 голосов
/ 27 августа 2009

Расширение объекта JavaScript Array - очень плохая идея, потому что вы вводите новые свойства (ваши пользовательские методы) в циклы for-in, которые могут нарушать существующие сценарии. Несколько лет назад авторам библиотеки Prototype пришлось изменить конструкцию своей библиотеки, чтобы удалить именно такие вещи.

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

27 голосов
/ 23 декабря 2009

Подумав секунду, если вы делаете этот вызов много раз, гораздо эффективнее использовать ассоциативный массив Map для поиска с использованием хеш-функции.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...