Как проверить, содержит ли массив объект в JavaScript?

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

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

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

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

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

вопрос задан 25.10.2008
brad
28488 репутация

41 ответов


  • 3711 рейтинг

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

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

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

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

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

    Некоторые другие структуры предлагают аналогичные методы:

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

    ответ дан codeape, с репутацией 69030, 24.09.2009
  • 363 рейтинг

    Обновление. Как упоминает @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
     
    ответ дан Damir Zekić, с репутацией 12005, 25.10.2008
  • 161 рейтинг

    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 показывает (например, это один ).

    ответ дан cic, с репутацией 5620, 25.10.2008
  • 133 рейтинг

    В 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 , использующего Strict Equality Comparison , includes сравнивается с использованием алгоритма равенства SameValueZero . Это означает, что вы можете определить, содержит ли массив массив NaN :

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

    Кроме того, в отличие от indexOf , includes не пропускает отсутствующие индексы:

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

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

    ответ дан Oriol, с репутацией 148439, 1.01.2015
  • 97 рейтинг

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

     function(a, b) {
        return a.indexOf(b) != -1
    }
     
    ответ дан william malo, с репутацией 1831, 24.03.2012
  • 67 рейтинг

    Вот совместимая с 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;
          };
    }
     
    ответ дан Már Örlygsson, с репутацией 11444, 27.10.2008
  • 48 рейтинг

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

     function isInArray(array, search)
    {
        return array.indexOf(search) >= 0;
    }
    
    // Usage
    if(isInArray(my_array, "my_value"))
    {
        //...
    }
     
    ответ дан Matías Cánepa, с репутацией 3258, 13.09.2013
  • 40 рейтинг

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

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

    ответ дан Már Örlygsson, с репутацией 11444, 27.08.2009
  • 40 рейтинг

    Верхние ответы предполагают примитивные типы, но если вы хотите узнать, содержит ли массив объект с некоторой чертой, 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

    ответ дан Michael, с репутацией 9586, 18.07.2014
  • 24 рейтинг

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

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

    ответ дан MattMcKnight, с репутацией 7077, 23.12.2009
  • 21 рейтинг

    Один лайнер:

     function contains(arr, x) {
        return arr.filter(function(elem) { return elem == x }).length > 0;
    }
     
    ответ дан AlonL, с репутацией 2420, 7.01.2015
  • 20 рейтинг

    Я использую следующее:

     Array.prototype.contains = function (v) {
        return this.indexOf(v) > -1;
    }
    
    var a = [ 'foo', 'bar' ];
    
    a.contains('foo'); // true
    a.contains('fox'); // false
     
    ответ дан Eduardo Cuomo, с репутацией 9021, 15.06.2014
  • 15 рейтинг
     function contains(a, obj) {
        return a.some(function(element){return element == obj;})
    }
     

    Array.prototype.some () был добавлен в стандарт ECMA-262 в пятом издании

    ответ дан dansalmo, с репутацией 7781, 12.09.2014
  • 12 рейтинг

    Надеюсь , быстрее двунаправленная indexOf /lastIndexOf альтернатива

    2015

    В то время как новый метод включает в себя очень хорошо, поддержка в настоящий момент равна нулю.

    Я долго думал о том, как заменить медленные функции indexOf /lastIndexOf.

    Уже был найден исполнительный путь, глядя на верхние ответы. От тех, что я выбрал contains функции, опубликованной @Damir Zekic, которая должна быть самой быстрой. Но в нем также говорится, что эталонные показатели с 2008 года и так устарели.

    Я также предпочитаю while более for , но не по какой-то конкретной причине я закончил писать функцию с циклом for. Это также можно сделать с помощью while -- .

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

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

    Двунаправленный индексOf /lastIndexOf

     function bidirectionalIndexOf(a, b, c, d, e){
      for(c=a.length,d=c*1; c--; ){
        if(a[c]==b) return c; //or this[c]===b
        if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
      }
      return -1
    }
    
    //Usage
    bidirectionalIndexOf(array,'value');
     

    Тест производительности

    http://jsperf.com/bidirectionalindexof

    В качестве теста я создал массив с 100 тыс. Записей.

    Три запроса: в начале, в середине и в конце массива.

    Надеюсь, вы также найдете это интересным и испытаете производительность.

    Примечание. Как вы можете видеть, я немного изменил функцию contains чтобы отразить вывод indexOf & lastIndexOf (так что в основном true с index и false с -1 ). Это не должно навредить ему.

    Вариант прототипа массива

     Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
      for(c=this.length,d=c*1; c--; ){
        if(this[c]==b) return c; //or this[c]===b
        if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
      }
      return -1
    },writable:false, enumerable:false});
    
    // Usage
    array.bidirectionalIndexOf('value');
     

    Функция также может быть легко изменена, чтобы возвращать true или false или даже объект, строку или что-то еще.

    И вот while вариант:

     function bidirectionalIndexOf(a, b, c, d){
      c=a.length; d=c-1;
      while(c--){
        if(b===a[c]) return c;
        if(b===a[d-c]) return d-c;
      }
      return c
    }
    
    // Usage
    bidirectionalIndexOf(array,'value');
     

    Как это возможно?

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

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

    http://jsperf.com/bidirectionalindexof/2

    ответ дан cocco, с репутацией 11897, 19.05.2015
  • 10 рейтинг

    Если вы неоднократно проверяете наличие объекта в массиве, вы должны, возможно, изучить

    1. Ведение массива отсортировано в любое время, выполнив сортировку в вашем массиве (поместите новые объекты в нужное место)
    2. Сделать обновления объектов в качестве операции удаления + сортировки вставки и
    3. Используйте поиск в двоичном поиске в contains(a, obj) .
    ответ дан Ztyx, с репутацией 5420, 5.02.2011
  • 10 рейтинг
     function inArray(elem,array)
    {
        var len = array.length;
        for(var i = 0 ; i < len;i++)
        {
            if(array[i] == elem){return i;}
        }
        return -1;
    } 
     

    Возвращает индекс массива, если найден, или -1, если не найден

    ответ дан LmC, с репутацией 2360, 27.06.2012
  • 9 рейтинг

    Мы используем этот фрагмент (работает с объектами, массивами, строками):

     /*
     * @function
     * @name Object.prototype.inArray
     * @description Extend Object prototype within inArray function
     *
     * @param {mix}    needle       - Search-able needle
     * @param {bool}   searchInKey  - Search needle in keys?
     *
     */
    Object.defineProperty(Object.prototype, 'inArray',{
        value: function(needle, searchInKey){
    
            var object = this;
    
            if( Object.prototype.toString.call(needle) === '[object Object]' || 
                Object.prototype.toString.call(needle) === '[object Array]'){
                needle = JSON.stringify(needle);
            }
    
            return Object.keys(object).some(function(key){
    
                var value = object[key];
    
                if( Object.prototype.toString.call(value) === '[object Object]' || 
                    Object.prototype.toString.call(value) === '[object Array]'){
                    value = JSON.stringify(value);
                }
    
                if(searchInKey){
                    if(value === needle || key === needle){
                    return true;
                    }
                }else{
                    if(value === needle){
                        return true;
                    }
                }
            });
        },
        writable: true,
        configurable: true,
        enumerable: false
    });
     

    Применение:

     var a = {one: "first", two: "second", foo: {three: "third"}};
    a.inArray("first");          //true
    a.inArray("foo");            //false
    a.inArray("foo", true);      //true - search by keys
    a.inArray({three: "third"}); //true
    
    var b = ["one", "two", "three", "four", {foo: 'val'}];
    b.inArray("one");         //true
    b.inArray('foo');         //false
    b.inArray({foo: 'val'})   //true
    b.inArray("{foo: 'val'}") //false
    
    var c = "String";
    c.inArray("S");        //true
    c.inArray("s");        //false
    c.inArray("2", true);  //true
    c.inArray("20", true); //false
     
    ответ дан dr.dimitru, с репутацией 2011, 10.09.2014
  • 8 рейтинг

    Используйте некоторую функцию lodash.

    Он лаконичен, точен и обладает большой поддержкой кросс-платформы.

    Принятый ответ даже не соответствует требованиям.

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

    Принятый ответ:

     $.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
    > -1
     

    Моя рекомендация:

     _.some([{'a': 1}, {'b': 2}], {'b': 2})
    > true
     

    Заметки:

    $ .inArray отлично подходит для определения, существует ли скалярное значение в массиве скаляров ...

     $.inArray(2, [1,2])
    > 1
     

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

    Чтобы обрабатывать как скаляры, так и объекты, вы можете сделать это:

     (_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
     
    ответ дан l3x, с репутацией 16774, 21.10.2015
  • 8 рейтинг

    Если вы используете JavaScript 1.6 или более поздней версии (Firefox 1.5 или новее), вы можете использовать Array.indexOf . В противном случае, я думаю, вы закончите с чем-то похожим на ваш исходный код.

    ответ дан Glomek, с репутацией 18875, 25.10.2008
  • 7 рейтинг

    В то время как array.indexOf(x)!=-1 является наиболее кратким способом сделать это (и был поддержан браузерами не Internet Explorer более десятилетия ...), это не O (1), а скорее O (N), что ужасно. Если ваш массив не изменится, вы можете преобразовать свой массив в хеш-таблицу, затем выполните table[x]!==undefined или ===undefined :

     Array.prototype.toTable = function() {
        var t = {};
        this.forEach(function(x){t[x]=true});
        return t;
    }
     

    Демо-версия:

     var toRemove = [2,4].toTable();
    [1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
     

    (К сожалению, в то время как вы можете создать Array.prototype.contains, чтобы «заморозить» массив и сохранить хэш-таблицу в this._cache в двух строках, это приведет к неправильным результатам, если вы захотите позже отредактировать свой массив. В JavaScript недостаточно крючков для позвольте вам сохранить это состояние, в отличие от Python, например.)

    ответ дан ninjagecko, с репутацией 56967, 22.04.2012
  • 6 рейтинг

    ECMAScript 6 имеет элегантное предложение по поиску.

    Метод find выполняет функцию обратного вызова один раз для каждого элемента, присутствующего в массиве, до тех пор, пока не найдет тот, где обратный вызов возвращает истинное значение. Если такой элемент найден, find немедленно возвращает значение этого элемента. В противном случае find возвращает undefined. callback вызывается только для индексов массива, которым присвоены значения; он не вызывается для индексов, которые были удалены или которые никогда не были присвоены значениям.

    Ниже приведена документация MDN .

    Функция поиска работает так.

     function isPrime(element, index, array) {
        var start = 2;
        while (start <= Math.sqrt(element)) {
            if (element % start++ < 1) return false;
        }
        return (element > 1);
    }
    
    console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
    console.log( [4, 5, 8, 12].find(isPrime) ); // 5
     

    Вы можете использовать это в ECMAScript 5 и ниже, определив функцию .

     if (!Array.prototype.find) {
      Object.defineProperty(Array.prototype, 'find', {
        enumerable: false,
        configurable: true,
        writable: true,
        value: function(predicate) {
          if (this == null) {
            throw new TypeError('Array.prototype.find called on null or undefined');
          }
          if (typeof predicate !== 'function') {
            throw new TypeError('predicate must be a function');
          }
          var list = Object(this);
          var length = list.length >>> 0;
          var thisArg = arguments[1];
          var value;
    
          for (var i = 0; i < length; i++) {
            if (i in list) {
              value = list[i];
              if (predicate.call(thisArg, value, i, list)) {
                return value;
              }
            }
          }
          return undefined;
        }
      });
    }
     
    ответ дан Pradeep Mahdevu, с репутацией 6981, 29.05.2014
  • 6 рейтинг

    Решение, которое работает во всех современных браузерах:

     function contains(arr, obj) {
      const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
      return arr.some(item => JSON.stringify(item) === stringifiedObj);
    }
     

    Применение:

     contains([{a: 1}, {a: 2}], {a: 1}); // true
     

    Решение IE6 +:

     function contains(arr, obj) {
      var stringifiedObj = JSON.stringify(obj)
      return arr.some(function (item) {
        return JSON.stringify(item) === stringifiedObj;
      });
    }
    
    // .some polyfill, not needed for IE9+
    if (!('some' in Array.prototype)) {
      Array.prototype.some = function (tester, that /*opt*/) {
        for (var i = 0, n = this.length; i < n; i++) {
          if (i in this && tester.call(that, this[i], i, this)) return true;
        } return false;
      };
    }
     

    Применение:

     contains([{a: 1}, {a: 2}], {a: 1}); // true
     

    Зачем использовать JSON.stringify ?

    Array.indexOf и Array.includes (как и большинство ответов здесь) сравниваются только по ссылке, а не по значению.

     [{a: 1}, {a: 2}].includes({a: 1});
    // false, because {a: 1} is a new object
     

    бонус

    Неоптимизированный однослойный ES6:

     [{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
    // true
     

    Примечание. Сравнение объектов по значению будет работать лучше, если ключи находятся в одном порядке, поэтому для обеспечения безопасности вы можете сначала сортировать ключи с помощью такого пакета: https://www.npmjs.com/package/sort-keys


    Обновлена ​​функция contains с первичной оптимизацией. Спасибо, что указал на это.

    ответ дан Igor Barbashin, с репутацией 372, 25.01.2017
  • 5 рейтинг

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

     var myArray = ['yellow', 'orange', 'red'] ;
    
    alert(!!~myArray.indexOf('red')); //true
     

    демонстрация

    Чтобы точно знать, что делают tilde ~ в этой точке, обратитесь к этому вопросу. Что делает тильда, когда она предшествует выражению? ,

    ответ дан Mina Gabriel, с репутацией 9234, 6.10.2013
  • 3 рейтинг

    Вы также можете использовать этот трюк:

     var arrayContains = function(object) {
      return (serverList.filter(function(currentObject) {
        if (currentObject === object) {
          return currentObject
        }
        else {
          return false;
        }
      }).length > 0) ? true : false
    }
     
    ответ дан user2724028, с репутацией 271, 10.01.2016
  • 3 рейтинг

    Хорошо, вы можете просто оптимизировать свой код, чтобы получить результат! Есть много способов сделать это, которые чище и лучше, но я просто хотел получить ваш шаблон и применить к нему с помощью JSON.stringify , просто просто сделайте что-нибудь подобное в своем случае:

     function contains(a, obj) {
        for (var i = 0; i < a.length; i++) {
            if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
                return true;
            }
        }
        return false;
    }
     
    ответ дан Alireza, с репутацией 39782, 2.07.2017
  • 3 рейтинг

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

     Array.prototype.contains = function(x){
      var retVal = -1;
    
      // x is a primitive type
      if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
    
      // x is a function
      else if(typeof x =="function") for(var ix in this){
        if((this[ix]+"")==(x+"")) retVal = ix;
      }
    
      //x is an object...
      else {
        var sx=JSON.stringify(x);
        for(var ix in this){
          if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
        }
      }
    
      //Return False if -1 else number if numeric otherwise string
      return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
    }
     

    Я знаю, что это не лучший способ, но, поскольку нет естественного способа сопоставления между объектами IComparable, я думаю, это так близко, что вы можете сравнить два объекта в массиве. Кроме того, расширение объекта Array может быть неразумным, но иногда это нормально (если вы знаете об этом и компромисс).

    ответ дан Carlos A, с репутацией 31, 6.01.2012
  • 3 рейтинг

    Можно использовать Set, который имеет метод «has ()»:

     function contains(arr, obj) {
      var proxy = new Set(arr);
      if (proxy.has(obj))
        return true;
      else
        return false;
    }
    
    var arr = ['Happy', 'New', 'Year'];
    console.log(contains(arr, 'Happy'));
     
    ответ дан rlib, с репутацией 3050, 16.11.2015
  • 3 рейтинг

    Вот как это делает Prototype :

     /**
     *  Array#indexOf(item[, offset = 0]) -> Number
     *  - item (?): A value that may or may not be in the array.
     *  - offset (Number): The number of initial items to skip before beginning the
     *      search.
     *
     *  Returns the position of the first occurrence of `item` within the array &mdash; or
     *  `-1` if `item` doesn't exist in the array.
    **/
    function indexOf(item, i) {
      i || (i = 0);
      var length = this.length;
      if (i < 0) i = length + i;
      for (; i < length; i++)
        if (this[i] === item) return i;
      return -1;
    }
     

    Также смотрите здесь, как они подключаются.

    ответ дан Ken, с репутацией 3011, 27.08.2009
  • 2 рейтинг
    1. Либо используйте Array.indexOf (Object).
    2. С ECMA 7 можно использовать Array.includes (Object).
    3. С ECMA 6 вы можете использовать Array.find (FunctionName), где FunctionName является определяемой пользователем функцией для поиска объекта в массиве.

      Надеюсь это поможет!

    ответ дан kg11, с репутацией 624, 18.08.2017
  • 2 рейтинг

    Как уже упоминалось, вы можете использовать Array.indexOf , но он недоступен во всех браузерах. Вот код из https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf, чтобы он работал в старых браузерах.

    indexOf - последнее дополнение к стандарту ECMA-262; как таковой, он не может присутствовать во всех браузерах. Вы можете обойти это, вставив следующий код в начале ваших сценариев, позволяя использовать indexOf в реализациях, которые его не поддерживают. Этот алгоритм точно такой, который указан в ECMA-262, 5th edition, при условии, что Object, TypeError, Number, Math.floor, Math.abs и Math.max имеют свое первоначальное значение.

     if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
            "use strict";
            if (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 > 1) {
                n = Number(arguments[1]);
                if (n != n) { // shortcut for verifying if it's NaN
                    n = 0;
                } else if (n != 0 && n != Infinity && n != -Infinity) {
                    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;
        }
    }
     
    ответ дан Simon_Weaver, с репутацией 68158, 12.03.2013
  • 2 рейтинг

    Отнюдь не лучшее, но я просто стал творческим и добавлял в репертуар.

    Не используйте это

     Object.defineProperty(Array.prototype, 'exists', {
      value: function(element, index) {
    
        var index = index || 0
    
        return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
      }
    })
    
    
    // Outputs 1
    console.log(['one', 'two'].exists('two'));
    
    // Outputs -1
    console.log(['one', 'two'].exists('three'));
    
    console.log(['one', 'two', 'three', 'four'].exists('four')); 

    ответ дан sqram, с репутацией 4263, 9.01.2016
  • 1 рейтинг

    Я просмотрел представленные ответы и понял, что они применяются только при поиске объекта по ссылке. Простой линейный поиск с сопоставлением ссылочного объекта.

    Но скажем, что у вас нет ссылки на объект, как вы найдете правильный объект в массиве? Вам придется идти линейно и глубоко по сравнению с каждым объектом. Представьте, если список слишком велик, а объекты в нем очень большие, содержащие большие фрагменты текста. Производительность резко падает с количеством и размером элементов в массиве.

    Вы можете стягивать объекты и помещать их в собственную хеш-таблицу, но тогда у вас будет избыточность данных, запоминающая эти ключи, потому что JavaScript сохраняет их для «для i в obj», и вы хотите только проверить, существует ли этот объект или нет, , у вас есть ключ.

    Я подумал об этом некоторое время, создав валидатор JSON Schema, и я разработал простую оболочку для собственной хеш-таблицы, аналогичную единственной реализации хэш-таблицы, с некоторыми исключениями оптимизации, которые я оставил в собственной хеш-таблице. Это требует только производительности бенчмаркинга ... Все детали и код можно найти в моем блоге: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ Я скоро опубликую результаты тестов.

    Полное решение работает следующим образом:

     var a = {'a':1,
     'b':{'c':[1,2,[3,45],4,5],
     'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
     'u':'lol'},
     'e':2};
    
     var b = {'a':1, 
     'b':{'c':[2,3,[1]],
     'd':{'q':3,'b':{'b':3}}},
     'e':2};
    
     var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
    
     var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
    
     hc.put({a:1, b:1});
     hc.put({b:1, a:1});
     hc.put(true);
     hc.put('true');
     hc.put(a);
     hc.put(c);
     hc.put(d);
     console.log(hc.exists('true'));
     console.log(hc.exists(a));
     console.log(hc.exists(c));
     console.log(hc.exists({b:1, a:1}));
     hc.remove(a);
     console.log(hc.exists(c));
     
    ответ дан stamat, с репутацией 909, 3.07.2013
  • 1 рейтинг

    Если вы работаете с ES6, вы можете использовать набор:

     function arrayHas( array, element ) {
        const s = new Set(array);
        return s.has(element)
    }
     

    Это должно быть более эффективным, чем любой другой метод

    ответ дан Neil Girardi, с репутацией 2372, 25.01.2018
  • 1 рейтинг

    Или это решение:

     Array.prototype.includes = function (object) {
      return !!+~this.indexOf(object);
    };
     
    ответ дан Tefa, с репутацией 266, 19.06.2017
  • 1 рейтинг

    Аналогичная вещь: Находит первый элемент «поисковой лямбдой»:

     Array.prototype.find = function(search_lambda) {
      return this[this.map(search_lambda).indexOf(true)];
    };
     

    Применение:

     [1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
    => 4
     

    То же самое в coffeescript:

     Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
     
    ответ дан Andy Rohr, с репутацией 41, 23.11.2012
  • 1 рейтинг

    Я работал над проектом, в котором мне нужна была такая функциональность, как python set которая удаляет все значения дубликатов и возвращает новый список, поэтому я написал эту функцию, возможно, полезную для кого-то

     function set(arr) {
        var res = [];
        for (var i = 0; i < arr.length; i++) {
            if (res.indexOf(arr[i]) === -1) {
                res.push(arr[i]);
            }
        }
        return res;
    }
     
    ответ дан Jeeva, с репутацией 485, 5.09.2017
  • 1 рейтинг

    Я рекомендовал использовать библиотеку underscore, потому что она возвращает значение и поддерживается для всех браузеров.

    underscorejs

      var findValue = _.find(array, function(item) {
        return item.id == obj.id;
     });
     
    ответ дан Durgpal Singh, с репутацией 4424, 26.06.2018
  • 1 рейтинг

    Он имеет один параметр: количество массивов объектов. Каждый объект в массиве имеет два целочисленных свойства, обозначаемых x и y. Функция должна возвращать счетчик всех таких объектов в массиве, которые удовлетворяют numbers.x == numbers.y

     var numbers = [ { x: 1, y: 1 },
                     { x: 2, y: 3 },
                     { x: 3, y: 3 },
                     { x: 3, y: 4 },
                     { x: 4, y: 5 } ];
        count = 0; 
    var n = numbers.length;
    for (var i =0;i<n;i++)
    {
      if(numbers[i].x==numbers[i].y)
      {count+=1;}
    }
    
    alert(count);
     
    ответ дан Mitul Panchal, с репутацией 62, 5.12.2017
  • 0 рейтинг

    Использование idnexOf () это хорошее решение, но вы должны скрыть встроенную функцию indexOf (), которая возвращает -1 с ~ оператором:

     function include(arr,obj) { 
        return !!(~arr.indexOf(obj)); 
    } 
     
    ответ дан KRRySS, с репутацией 63, 2.08.2017
  • -4 рейтинг

    Еще один вариант

     // usage: if ( ['a','b','c','d'].contains('b') ) { ... }
    Array.prototype.contains = function(value){
        for (var key in this)
            if (this[key] === value) return true;
        return false;
    }
     
    ответ дан Dennis Allen, с репутацией 315, 4.08.2010
  • -6 рейтинг

    Буквально:

    (используя Firefox v3.6, с for-in предостережениями, как было отмечено ранее (ОДНАКО, использование ниже может поддержать for-in для этой цели! То есть перечисление элементов массива, которые ACTUALLY существуют через индекс свойств (HOWEVER, в частности, свойство array length НЕ перечислены в for-in списках собственности!).).).)

    (Перетащите следующие полные URI для немедленного тестирования браузера в режиме браузера).

    JavaScript:

       function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}
    
      function check(ra){
          return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
      }
      alert([
                check([{}]), check([]), check([,2,3]),
                check(['']), '\t (a null string)', check([,,,])
            ].join('\n'));
     

    который отображает:

     There is an object in [[object Object]].
    There is NO object in [].
    There is an object in [,2,3].
    There is an object in [].
         (a null string)
    There is NO object in [,,].
     

    Морщины: если вы ищете «конкретный» объект, подумайте:

    JavaScript: alert({}!={}); alert({}!=={});

    И поэтому:

    JavaScript:

      obj = {prop:"value"}; 
     ra1 = [obj]; 
     ra2 = [{prop:"value"}];
     alert(ra1[0] == obj); 
     alert(ra2[0] == obj);
     

    Часто ra2 считается «содержать» obj как буквальное сущность {prop:"value"} .

    Очень грубое, рудиментарное, наивное (как в коде нуждается повышение квалификации):

    JavaScript:

       obj={prop:"value"};   ra2=[{prop:"value"}];
      alert(
        ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
          'found' :
          'missing' );
     

    См. Ссылку: Поиск объектов в массивах JavaScript .

    ответ дан Ekim, с репутацией 515, 10.05.2011