javascript - объектов - поиск в массиве js
Как проверить, содержит ли массив объект в JavaScript? (20)
ECMAScript 6 имеет элегантное предложение по поиску.
Метод find выполняет функцию обратного вызова один раз для каждого элемента, присутствующего в массиве, до тех пор, пока не найдет тот, где обратный вызов возвращает истинное значение. Если такой элемент найден, find немедленно возвращает значение этого элемента. В противном случае find возвращает undefined. callback вызывается только для индексов массива, которым присвоены значения; он не вызывается для индексов, которые были удалены или которые никогда не были присвоены значениям.
Функция поиска работает так.
Вы можете использовать это в ECMAScript 5 и ниже, определив функцию .
Каков наиболее сжатый и эффективный способ узнать, содержит ли массив JavaScript объект?
Это единственный способ, которым я это знаю:
Есть ли лучший и более сжатый способ сделать это?
Это очень тесно связано с вопросом о переполнении стека. Лучший способ найти элемент в массиве JavaScript? который адресует поиск объектов в массиве с помощью indexOf .
В ECMAScript 7 представлен array.includes(value) .
Его можно использовать следующим образом:
Он также принимает необязательный второй аргумент fromIndex :
В отличие от indexOf , который использует Strict Equality Comparison , includes сравнения с использованием алгоритма равенства SameValueZero . Это означает, что вы можете определить, содержит ли массив NaN :
Кроме того, в отличие от indexOf , indexOf не пропускает отсутствующие индексы:
В настоящее время он по-прежнему является черновиком, но может быть polyfill чтобы он работал на всех браузерах.
В то время как array.indexOf(x)!=-1 является наиболее кратким способом сделать это (и был поддержан браузерами не Internet Explorer более десятилетия . ), это не O (1), а скорее O ( N), что ужасно. Если ваш массив не изменится, вы можете преобразовать свой массив в хеш- table[x]!==undefined , а затем сделать table[x]!==undefined или ===undefined :
(К сожалению, в то время как вы можете создать Array.prototype.contains, чтобы «заморозить» массив и сохранить хэш-таблицу в this._cache в двух строках, это приведет к неправильным результатам, если вы захотите позже отредактировать свой массив. В JavaScript недостаточно крючков для позвольте вам сохранить это состояние, в отличие от Python, например.)
Верхние ответы предполагают примитивные типы, но если вы хотите узнать, содержит ли массив объект с некоторой чертой, Array.prototype.some() - очень изящное решение:
Самое приятное в том, что итерация прерывается после обнаружения элемента, поэтому сохраняются ненужные итерационные циклы.
Кроме того, он отлично вписывается в оператор if поскольку он возвращает логическое значение:
* Как отметил jamess в комментарии, на сегодняшний день, сентябрь 2018 года, Array.prototype.some() полностью поддерживается: таблица поддержки caniuse.com
Вы также можете использовать этот трюк:
Если вы используете JavaScript 1.6 или более поздней версии (Firefox 1.5 или новее), вы можете использовать Array.indexOf . В противном случае, я думаю, вы закончите с чем-то похожим на ваш исходный код.
Я знаю, что это не лучший способ, но, поскольку нет естественного способа сопоставления между объектами IComparable, я думаю, это так близко, что вы можете сравнить два объекта в массиве. Кроме того, расширение объекта Array может быть неразумным, но иногда это нормально (если вы знаете об этом и компромисс).
Используйте some функцию lodash.
Он лаконичен, точен и обладает большой поддержкой кросс-платформы.
Принятый ответ даже не соответствует требованиям.
Требования: рекомендуйте наиболее сжатый и эффективный способ узнать, содержит ли массив JavaScript объект.
Принятый ответ:
Моя рекомендация:
$ .inArray отлично подходит для определения, существует ли скалярное значение в массиве скаляров .
. но вопрос явно требует эффективного способа определить, содержится ли объект в массиве.
Чтобы обрабатывать как скаляры, так и объекты, вы можете сделать это:
Как уже упоминалось, вы можете использовать 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 имеют свое первоначальное значение.
Мы используем этот фрагмент (работает с объектами, массивами, строками):
Использование:
Ниже приведена Array.indexOf JavaScript, совместимая с JavaScript 1.6 : Array.indexOf :
Размышляя о коробке на секунду, если вы делаете этот вызов много раз, гораздо эффективнее использовать ассоциативный массив, который будет выполнять поиск, используя хеш-функцию.
Расширение объекта JavaScript Array - действительно плохая идея, потому что вы вводите новые свойства (ваши собственные методы) for-in циклы for-in которые могут нарушать существующие скрипты. Несколько лет назад авторам библиотеки Prototype пришлось перестроить свою библиотечную реализацию, чтобы удалить именно такую вещь.
Если вам не нужно беспокоиться о совместимости с другим JavaScript, запущенным на вашей странице, пойдите для этого, иначе я бы рекомендовал более неудобное, но более безопасное решение для самостоятельной работы.
Хорошо, вы можете просто оптимизировать свой код, чтобы получить результат! Есть много способов сделать это, что чище и лучше, но я просто хотел получить ваш шаблон и применить к нему с помощью JSON.stringify , просто просто сделайте что-то вроде этого в вашем случае:
Я использую следующее:
b - значение, a - массив. Он возвращает true или false :
indexOf более быстрая двунаправленная indexOf / lastIndexOf
В то время как новый метод array.includes(value) очень хорошо, поддержка в настоящий момент равна нулю.
Я долго думал о том, как заменить медленные функции indexOf / lastIndexOf.
Уже был найден исполнительный путь, глядя на верхние ответы. Из тех, что я выбрал, contains функцию, опубликованную @Damir Zekic, которая должна быть самой быстрой. Но в нем также говорится, что эталонные показатели с 2008 года и так устарели.
Я также предпочитаю, while закончили, но не по какой-то конкретной причине я закончил писать функцию с циклом for. Это может быть сделано и через некоторое while -- .
Мне было любопытно, если итерация была намного медленнее, если я проверяю обе стороны массива, делая это. По-видимому, нет, и поэтому эта функция примерно в два раза быстрее, чем верхние проголосовавшие. Очевидно, что он также быстрее, чем родной. Это в реальной среде, где вы никогда не знаете, находится ли значение, которое вы ищете, в начале или в конце массива.
Когда вы знаете, что просто нажали массив со значением, использование lastIndexOf остается, пожалуй, лучшим решением, но если вам нужно путешествовать по большим массивам, и результат может быть повсюду, это может быть надежным решением для ускорения работы.
Двунаправленный индексOf / lastIndexOf
Тест производительностиВ качестве теста я создал массив с 100 тыс. Записей.
Три запроса: в начале, в середине и в конце массива.
Надеюсь, вы также найдете это интересным и испытаете производительность.
Примечание. Как вы можете видеть, я слегка изменил функцию contains чтобы отразить вывод indexOf & lastIndexOf (так что в основном true с index и false с -1 ). Это не должно навредить ему.
Вариант прототипа массиваФункция также может быть легко изменена, чтобы возвращать true или false или даже объект, строку или что-то еще.
Как это возможно?Я думаю, что простой расчет для получения отраженного индекса в массиве настолько прост, что он в два раза быстрее, чем выполнение фактической итерации цикла.
Вот сложный пример, выполняющий три проверки на итерацию, но это возможно только при более длительном вычислении, которое вызывает замедление кода.