it-swarm.com.ru

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

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

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

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

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

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

3459
brad

Текущие браузеры имеют 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.

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

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

3894
codeape

Обновление: как @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
374
Damir Zekić

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

169
cic

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

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

140
Oriol

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

function(a, b) {
    return a.indexOf(b) != -1
}
100
william malo

Вот 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;
        };
}
71
Már Örlygsson

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

66
Michael

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

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

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
50
Matías Cánepa

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

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

42
Mason Houtz

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

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

27
MattMcKnight

Один лайнер:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
24
AlonL

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

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false
22
Eduardo Cuomo
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

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

19
dansalmo

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

2015

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

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

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

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

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

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

Двунаправленный indexOf/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

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

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

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

Примечание: Как вы можете видеть, я немного изменил функцию 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');

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

А вот вариант 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

14
cocco

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

  1. Поддержание сортировки массива всегда с помощью сортировки вставок в вашем массиве (поместите новые объекты в нужное место) 
  2. Сделать обновление объектов как удаление + сортировка операции вставки и
  3. Используйте бинарный поиск lookup в вашей contains(a, obj).
12
Ztyx

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

/*
 * @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
12
dr.dimitru
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

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

12
LmC

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

10
Andru Luvisi

Используйте функцию Лодаша некоторые .

Это сжато, точно и имеет большую поддержку кроссплатформенности.

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

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

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

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

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

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

Заметки: 

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

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

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

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

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
9
l3x

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

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/ пакет/сортировка ключей


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

9
Igor Barbashin

Хотя 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, например.)

8
ninjagecko

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

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

Вот документация 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;
    }
  });
}
7
Pradeep Mahdevu

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

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

Демо

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

6
Mina Gabriel

Вот как Прототип это делает :

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

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

4
Ken

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

var arrayContains = function(object) {
  return (serverList.filter(function(currentObject) {
    if (currentObject === object) {
      return currentObject
    }
    else {
      return false;
    }
  }).length > 0) ? true : false
}
3
user2724028

ОК, вы можете просто оптимизировать ваш код, чтобы получить результат! 

Есть много способов сделать это, которые будут чище и лучше, но я просто хотел получить ваш шаблон и применить к нему, используя 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;
}
3
Alireza

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

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 может быть неуместным, но иногда это нормально (если вы знаете об этом и компромиссе).

3
Carlos A

Можно использовать 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'));
3
rlib
  1. Либо используйте Array.indexOf(Object)
  2. С ECMA 7 можно использовать Array.includes(Object)
  3. В ECMA 6 вы можете использовать функцию Array.find(FunctionName), где FunctionName - определенная пользователем Функция для поиска объекта в массиве.

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

2
kg11

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

indexOf - недавнее дополнение к стандарту ECMA-262; как таковой он может не присутствовать во всех браузерах. Вы можете обойти это, вставив следующий код в начале ваших скриптов, позволяющий использовать indexOf в реализациях, которые изначально не поддерживают его. Это Алгоритм точно такой, который указан в ECMA-262, 5-е издание, при условии 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;
    }
}
2
Simon_Weaver

Удивлен, что этот вопрос до сих пор не добавлен последний синтаксис, добавив мои 2 цента.

Допустим, у нас есть массив объектов arrObj, и мы хотим найти в нем объект obj.

Array.prototype. indexOf -> (возвращает индекс или -1 ) обычно используется для поиска индекса элемента в массиве. Это также может быть использовано для поиска объекта, но работает, только если вы передаете ссылку на тот же объект.

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype. включает в себя -> (возвращает истина или ложь )

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype. find -> (принимает обратный вызов, возвращает первое значение/объект , которое возвращает true в CB).

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype. findIndex -> (принимает обратный вызов, возвращает index первого значения/объекта, который возвращает true в CB).

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

Поскольку find и findIndex принимают обратный вызов, мы можем извлечь любой объект (даже если у нас нет ссылки) из массива, творчески установив истинное условие.

2
Sumer

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

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

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'));

2
sqram

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

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

Вы можете упорядочить объекты и поместить их в собственную хеш-таблицу, но тогда у вас будет избыточность данных, запоминание этих ключей, потому что JavaScript сохраняет их для «for i in 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));
1
stamat

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

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

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

1
Neil Girardi

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

Array.prototype.includes = function (object) {
  return !!+~this.indexOf(object);
};
1
Tefa

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

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)]
1
Andy Rohr

Я работал над проектом, в котором мне нужна была такая функциональность, как 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;
}
1
Jeeva

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

подчеркивание

 var findValue = _.find(array, function(item) {
    return item.id == obj.id;
 });
1
Durgpal Singh

У него один параметр: массив номеров объектов. Каждый объект в массиве имеет два целочисленных свойства, обозначаемых 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);
1
Mitul Panchal

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

function include(arr,obj) { 
    return !!(~arr.indexOf(obj)); 
} 
0
KRRySS

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

let array = [1, 2, 3, 4, {"key": "value"}];

array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true

array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true

Array.some возвращает true, если какой-либо элемент соответствует данному условию, и возвращает false, если ни один из элементов не соответствует данному условию.

0
Nitesh Ranjan

Использование включает в себя встроенную функцию JavaScript

var optval = [];

optval.Push('A');    
optval.Push('B');    
optval.Push('C');

Мы можем искать строку A в массиве JavaScript как:

optval.includes('A') // =====> return true
0
Rajeev Ranjan

Простое решение: ES6 Особенности " включает " метод

let arr = [1, 2, 3, 2, 3, 2, 3, 4];

  arr.includes(2) // true

  arr.includes(93) // false
0
ngCourse
function countArray(originalArray) {

    var compressed = [];
    // make a copy of the input array
    var copyArray = originalArray.slice(0);

    // first loop goes over every element
    for (var i = 0; i < originalArray.length; i++) {

        var count = 0;  
        // loop over every element in the copy and see if it's the same
        for (var w = 0; w < copyArray.length; w++) {
            if (originalArray[i] == copyArray[w]) {
                // increase amount of times duplicate is found
                count++;
                // sets item to undefined
                delete copyArray[w];
            }
        }

        if (count > 0) {
            var a = new Object();
            a.value = originalArray[i];
            a.count = count;
            compressed.Push(a);
        }
    }

    return compressed;
};

// It should go something like this:

var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = countArray(testArray);
console.log(newArray);
0
Sanjay Magar