Как проверить, включает ли массив значение в JavaScript?

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

Это единственный известный мне способ сделать это:

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

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

только что протестировано: ваш способ на самом деле самый быстрый для всех браузеров: jsperf.com/find-element-in-obj-vs-array/2 (кроме предварительного сохранения a.length в переменной) при использовании indexOf (как в $ .inArray) намного медленнее

Jörn Berkefeld 02.07.2012 15:56

многие ответили, что Array # indexOf - ваш лучший выбор. Но если вы хотите что-то, что может быть правильно преобразовано в логическое значение, используйте это: ~[1,2,3].indexOf(4) вернет 0, что будет оценено как ложь, тогда как ~[1,2,3].indexOf(3) вернет -3, что будет оцениваться как истина.

lordvlad 02.10.2013 11:59
~ - это не то, что вы хотите использовать для преобразования в логическое значение, для этого вам нужен !. Но в этом случае вы хотите проверить равенство с -1, так как функция может закончить return [1,2,3].indexOf(3) === -1;~ не является двоичным, она будет инвертировать каждый бит значения индивидуально.
mcfedr 20.06.2014 16:49

IE9 поддерживает indexOf() согласно w3schools.com/jsref/jsref_indexof_array.asp. Если в более старом браузере лучше всего определить prototype для функции indexOf(), как указано в Array.indexOf в Internet Explorer

LCJ 22.01.2015 00:42

@Iordvlad [1,2,3].indexOf(4) на самом деле будет возврат -1. Как указал @mcfedr, ~ - это побитовый оператор НЕ, см. ES5 11.4.8. Дело в том, что поскольку двоичное представление -1 состоит только из единиц, его дополнением является 0, который оценивается как ложный. Дополнение любого другого числа будет отличным от нуля, следовательно, истинным. Итак, ~ отлично работает и часто используется вместе с indexOf.

mknecht 14.03.2015 08:35

Название вводит в заблуждение. Где [[1,2],[3,4]].includes([3,4])?

mplungjan 02.04.2017 12:20

@brad, когда я впервые прочитал ваш вопрос, я не мог понять вашу идею, объект здесь - это объект javascript или примитивное значение. Допустим, у меня есть массив: const arr = [1, 2, 3, { foo: 1}];. И arr.includes(1) // true, но arr.includes({ foo: 1 }) //false

Chau Giang 05.06.2019 13:36
Если элементы в вашем массиве являются объектами затем посмотрите ответ это, который использует функцию some.
RBT 18.06.2019 12:51
let arr = ['apple','banana', 1, 2, 4] if (!arr.includes('banana') ) console.info('No') else console.info('Yes')
Jakaria Ridoy 29.04.2020 13:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4 308
9
2 823 395
54
Перейти к ответу Данный вопрос помечен как решенный

Ответы 54

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

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

Фактически, есть пример реализации расширения indexOf для браузеров, которые его не поддерживают, на странице developer.mozilla.org, на которую вы ссылаетесь.

Lloyd Cotten 25.03.2009 00:24

на самом деле, если вы добавите indexof к прототипу Array для браузеров, которые его не поддерживают (например, IE7), они также попытаются перебрать эту функцию при циклическом обходе элементов в массиве. противный.

CpILL 11.07.2012 13:13

применимо ли это для проверки объекта? я не думаю, что это работает в случае объекта

Himesh Aadeshara 25.05.2018 07:19

Обновление от 2019 года: этот ответ относится к 2008 году (11 лет!) И не актуален для современного использования JS. Обещанное улучшение производительности было основано на тестах, проведенных в браузерах того времени. Это может не иметь отношения к современным контекстам выполнения JS. Если вам нужно простое решение, поищите другие ответы. Если вам нужна лучшая производительность, протестируйте себя в соответствующих средах выполнения.

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

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

Конечно, вы также можете расширить прототип массива:

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

Но будьте осторожны: stackoverflow.com/questions/237104/javascript-array-contains‌ obj /…

MatrixFrog 13.08.2010 03:16

«Проверено» - сильное слово. Движки JS постоянно улучшаются, а время выполнения, измеренное 3 года назад, ужасно устарело.

orip 20.11.2011 12:09

@orip отличный момент. Но даже в этом случае для самого медленного браузера это все еще актуально. Для современных браузеров разница либо незначительна, либо несущественна (поскольку они уже поддерживают indexOf). Я обновил ответ, спасибо.

Damir Zekić 20.11.2011 14:40

@ Дамир - согласен. Возможно, измените образец, чтобы использовать indexOf, если он доступен, чтобы люди, слепо копирующие этот код, получили максимальную производительность.

orip 20.11.2011 16:45

расширение массива таким образом вызовет еще одну проблему. если вы используете for (x в myArray), он также будет циклически перебирать методы прототипа, поэтому вам нужно теперь проверить, является ли каждый x свойством. Я ищу прямо сейчас, чтобы увидеть, есть ли способ исправить это, не переделывая все мои for (in).

Chris Stephens 23.11.2011 01:28

вам следует использовать i in obj && ... === ..., потому что в случае разреженных массивов var arr=[];arr[4] = "d"; он ошибочно вернет true при поиске undefined

ajax333221 04.04.2012 23:04

+1 за предоставление ССЫЛКИ на доказательство времени итерации ... откровенные откровения в отношении цикла по элементам HTML ...

kumarharsh 22.08.2012 01:56

@cbmeeks да, уход определенно нужен. Вероятно, это был случай выполнения for (o in array), чего не следует делать при циклическом просмотре массива в целом ...

Damir Zekić 12.10.2012 17:18

Лучший способ сделать это - проверить, если [1, 2, 3] .indexOf (1)> -1

Devin Rhode 29.10.2012 03:25

Ваша функция contains работает во всех старых и новых браузерах?

Thomas 12.11.2014 20:03

что prototype () делает в js? используется ли он для добавления какого-либо расширения к любому классу или объекту извне?

Thomas 14.11.2014 15:53

В nodejs (v7.4.0) на моей 64-битной машине с Windows 7 поиск 1 в массиве с 10M нулями; цикл while занимает около 240+ мс, цикл for (также обратный отсчет) занимает около 220 мс, а метод indexOf занимает около 20 мс. Если я заполняю этот массив некоторыми увеличивающимися числами (от 0 до 10M-1) и ищу -1, цикл while становится быстрее примерно в 4 раза, цикл for становится быстрее примерно в 8 раз, а indexOf занимает примерно на 25-50% больше времени. Цвет меня удивил.

mkey 06.02.2017 18:32

Этот ответ должен быть отклонен или удален, поскольку это худшее решение для этой даты (в то время оно было достаточно хорошим).

Marco 05.08.2019 22:50

@ DamirZekić, я не думаю, что содержит метод в JS, включает правильный синтаксис здесь

jaideep_johny 03.09.2019 23:58

Заявления о производительности при таком подходе сомнительны. Во-первых, его обратное направление может давать ложные срабатывания в тестах, которые смещаются в сторону элементов в конце массива. С другой стороны, запуск теста в Perflink показывает, что этот код работает примерно на 9% от скорости includes (для элемента около середины массива), тогда как идентичный тест в jsBench показывает, что он приближается к includes или даже иногда опережает его. (Эти тесты проводились несколько раз для одного и того же браузера, версии браузера и компьютера.) Это странное несоответствие.

Abion47 16.04.2020 00:25

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

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

Выглядит великолепно, но немного сбивает с толку: * Разве тесты в строках 1 и 3 не эквивалентны? * Не лучше ли протестировать прототип и при необходимости добавить функцию в Array.prototype?

Avi Flax 11.07.2010 16:31

Они не эквивалентны. [].indexOf - это сокращение от Array.prototype.indexOf. Мы, параноидально защищающиеся Javascript-программисты, любой ценой избегаем расширения собственных прототипов.

Már Örlygsson 14.07.2010 16:03

Разве [].indexOf не создает новый массив, а затем обращается к indexOf, в то время как Array.prototype.indexOf просто обращается к прототипу напрямую?

alex 08.03.2011 14:47

@alex да [].indexOf === Array.prototype.indexOf (попробуйте в FireBug), но наоборот [].indexOf !== Array.indexOf.

Már Örlygsson 11.03.2011 16:32

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

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

Я не согласен. Именно по этой причине для массивов не следует использовать циклы For-in. Использование циклов for-in сломается при использовании одной из популярных библиотек js.

Tomas 18.02.2011 17:51

Будет ли это считаться исправлением обезьяны? lol Некоторым это нравится.

cbmeeks 11.10.2012 00:36

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

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

Также см. здесь, чтобы узнать, как они его подключают.

Ответ принят как подходящий

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

console.info(['joe', 'jane', 'mary'].includes('jane')); //true

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

console.info(['joe', 'jane', 'mary'].indexOf('jane') >= 0); //true

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

  • jQuery: $.inArray(value, array, [fromIndex])
  • Underscore.js: _.contains(array, value) (также называемый _.include и _.includes)
  • Инструментарий Dojo: dojo.indexOf(array, value, [fromIndex, findLast])
  • Прототип: array.indexOf(value)
  • MooTools: array.indexOf(value)
  • MochiKit: findValue(array, value)
  • MS Ajax: array.indexOf(value)
  • Внешний: Ext.Array.contains(array, value)
  • Lodash: _.includes(array, value, [from]) (это _.contains до 4.0.0)
  • Рамда: R.includes(value, array)

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

В MooTools также есть Array.contains, который возвращает логическое значение, что здесь звучит как настоящий вопрос.

Ryan Florence 08.06.2010 18:10

прототип также имеет Array.include, который возвращает логическое значение

user102008 11.09.2010 02:54

Если вы используете хороший браузер, вы можете просто использовать array.indexOf(object) != -1.

Sam Soffes 06.10.2010 20:17

@ user102008: MDN не содержит никаких ссылок на Array.include (Справочник по массиву MDN - я искал, какая версия JS была в нем.) Где вы видели ссылку на этот метод?

zcrar70 12.07.2011 14:06

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

plus- 29.02.2012 21:17
inArray - ужасное имя для функции, возвращающей индекс элемента, и -1, если он не существует. Я ожидал, что будет возвращено логическое значение.
Tim 22.07.2012 13:45
var inArray = function(a,b,c,d){for(c in b)d|=b[c]===a;return!!d }
Om Shankar 30.12.2012 22:54

убрать подчеркивание включил?

jcolebrand 16.01.2013 08:04

@jcolebrand Я обновил ответ. include все еще существует, но в документации указан как псевдоним для contains

codeape 16.01.2013 13:11

@Tim, я думаю, он возвращает -1, чтобы свести на нет вероятность того, что 0 будет принят как ложь

Relequestual 19.08.2013 16:46

Я думаю, что кто-то упомянул, что вы можете получить около 0, которое будет оценено как ложное, используя оператор ===, хотя бы мимоходом.

Aaron Mason 11.07.2014 03:15

Я думал, что дротик - это родной язык. Он действительно компилируется в JS? Обновлено: о, его можно скомпилировать в JS, хотя он лучше всего работает в браузере, созданном для его запуска.

DanielST 22.10.2014 00:31

@IulianOnofrei: Нет, 2 in [1,2,3] == true, но 5 in [3,4,5] == false. Почему? Поскольку массивы в сценариях JavaScripts ведут себя так же, как обычные объекты, 2 in array фактически означает только то, что array[2] определен. Имейте в виду, что это поведение все еще потенциально полезно, поскольку массивы JavaScript могут быть разреженными: 2 in [1,2,,3] == false

Witiko 21.03.2015 18:44

Вы также должны проверить это предложение: github.com/tc39/Array.prototype.includes Также это для различных способов использования Array.prototype.indexOf(): codereview.stackexchange.com/questions/13941/…

AlicanC 06.04.2015 16:09

Почему бы не привести в ответ пример? if ($.inArray(value, array)) > -1 { // found value in array }

Avatar 07.04.2015 18:50

сейчас 2016, и я все еще не могу правильно использовать .include и .indexOf для типа non primitive.

Adi Prasetyo 29.02.2016 21:47

Но ничего из этого не будет работать для массива сложного типа? он работает со строками, числами и всем, что abt var arr = [{"id": "1", "name": "Joe"}, {"id": "2", "name": "Smith"} ]; var obj = {"id": "1", "name": "Joe"}; arr.includes (obj);

Kay Gee 12.10.2018 19:23
array.includes(foo) не поддерживает объекты. Я не уверен, почему это принятый ответ, потому что он был задан Как проверить, включает ли массив объект в JavaScript?
Stophface 24.10.2018 09:40

"широко" вводит в заблуждение, поскольку IE 11 его не поддерживает

Tomasz Smykowski 21.03.2019 17:20

Мне просто нужно запомнить indexOf для стендов Array и String :) на всякий случай.

user985399 26.06.2019 18:03

как проверить ключ и значение с помощью включения?

Kapil soni 02.07.2019 07:51

возможно, используйте IndexOf ^^

Sandro Schaurer 10.07.2019 12:47

у этого ответа так много голосов, но вопрос касается объектов в массивах, с которыми это не работает.

Emobe 03.08.2019 00:30

@Stophface @Emobe Как это может быть неправильный ответ? В вопросе задавались способы сделать то же самое, что и в предоставленном коде. И Array#includes делает именно то, что делает код в вопросе.

Robert 08.01.2020 00:25

Отличный ответ. ПРИМЕЧАНИЕ. includesindexOf) НЕ преобразовывают тип. Вам нужно будет сделать это в коде, я полагаю, console.info(['joe', 'jane', 'mary', 46].includes(Number('46')));

ow3n 17.09.2020 18:41

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

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

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

Pie 'Oh' Pah 11.12.2018 22:27

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

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

Будьте осторожны, поскольку перегрузка объектов массива javascript пользовательскими методами может нарушить поведение других сценариев JavaScript, вызывая неожиданное поведение.

Но будьте осторожны: stackoverflow.com/questions/237104/javascript-array-contains‌ obj /…

MatrixFrog 13.08.2010 03:18

Пожалуйста, не используйте цикл for in для итерации по массиву - циклы for in следует использовать только для объектов.

Yi Jiang 20.01.2011 19:33

почему это так плохо

da coconut 08.06.2020 13:23

пожалуйста, не отменяйте встроенные developers.google.com/web/updates/2018/03/smooshgate

nkitku 28.10.2020 22:05

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

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

Или, если возможно, полностью прекратите использование массива и вместо этого используйте объект в качестве словаря, как предлагали MattMcKnight и ninjagecko.

joeytwiddle 08.07.2013 21:08

Буквально:

(с использованием Firefox v3.6, с оговорками for-in, как отмечалось ранее (ОДНАКО приведенное ниже использование может поддерживать for-in именно для этой цели! То есть перечисление элементов массива, которые ДЕЙСТВИТЕЛЬНО существуют через индекс свойства (ОДНАКО, в частности, свойство массива 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.

Использовать:

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

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

Heretic Monkey 10.10.2019 18:13

Допустим, вы определили такой массив:

const array = [1, 2, 3, 4]

Ниже приведены три способа проверить, есть ли там 3. Все они возвращают либо true, либо false.

Метод Native Array (начиная с ES2016) (таблица совместимости)

array.includes(3) // true

Как настраиваемый метод массива (до ES2016)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

Простая функция

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

Он возвращает истину, если "b" находится в массиве "a" ... Я не знаю, как еще это объяснить ...

william malo 16.06.2012 04:41

Я не понимаю "!! ~". И я думаю, что это не сработает в IE8, потому что IE8 не поддерживает indexOf () для объекта Array.

svlada 18.06.2012 09:29

«~» - это оператор, который увеличивает, инвертирует и вычитает 1 из числа. indexOf возвращает -1 в случае неудачи, поэтому "~" превращает -1 в "0". с использованием "!!" превращает числа в булевы (!! 0 === false)

william malo 19.06.2012 18:41

Круто, но серьезно для простоты y не просто a.indexOf (b)> - 1, так как "> -1" .length === "!! ~" .length

user2039981 16.12.2014 18:35

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

okdewit 19.01.2016 14:18

Хотя 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.)

function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if (array[i] == elem){return i;}
    }
    return -1;
} 

Возвращает индекс массива, если найден, или -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)]

Это, безусловно, гораздо более гибкий подход, чем многие другие подходы. Если прототип не устраивает, можно рассмотреть что-то вроде var positionIf = function (предикат, последовательность) {return sequence.map (predicate) .indexOf (true);};

dat 06.06.2013 01:28

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

Casey Chu 10.10.2013 08:49

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

indexOf is a recent addition to the ECMA-262 standard; as such it may not be present in all browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of indexOf in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max have their original value.

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

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

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

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

Я некоторое время думал об этом, создавая валидатор схемы JSON, и разработал простую оболочку для собственной хэш-таблицы, похожую на реализацию единственной хеш-таблицы, с некоторыми исключениями оптимизации, которые я оставил для работы с собственной хеш-таблицей. Нужен только тест производительности ... Все подробности и код можно найти в моем блоге: 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.info(hc.exists('true'));
 console.info(hc.exists(a));
 console.info(hc.exists(c));
 console.info(hc.exists({b:1, a:1}));
 hc.remove(a);
 console.info(hc.exists(c));

Использовать:

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

// Usage
if (isInArray(my_array, "my_value"))
{
    //...
}
x ? true : false обычно избыточен. Это здесь.
Ry- 26.02.2014 20:38

@minitech Почему вы говорите, что это лишнее?

Matías Cánepa 03.05.2014 19:40
array.indexOf(search) >= 0 уже является логическим. Просто return array.indexOf(search) >= 0.
Ry- 03.05.2014 21:38

@minitech ну спасибо! На самом деле я не знал, что такую ​​конструкцию можно вернуть. TIL что-то новое.

Matías Cánepa 29.07.2014 22:25

Буквально любая конструкция в javascript может быть возвращена

B T 16.01.2015 01:20

Использовать:

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

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

Демо

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

Это уже было опубликовано полтора года назад, повторять не нужно.

Shadow The Vaccinated Wizard 06.10.2013 16:33

На самом деле он не был опубликован. Не как ответ, а как комментарий к ответу, да и то не ясно и лаконично. Спасибо за публикацию, Мина Габриэль.

T.CK 15.05.2018 17:52

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

The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.

Вот Документация MDN по этому поводу.

Функция поиска работает следующим образом.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.info( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.info( [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;
    }
  });
}

Теперь это стандарт: ecma-international.org/ecma-262/6.0/#sec-array.prototype.fin‌ d

Madbreaks 16.08.2016 20:38

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

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

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

a.contains('foo'); // true
a.contains('fox'); // false

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

* Как указал Джеймс в комментарии, на момент этого ответа, сентябрь 2018 г., Array.prototype.some() полностью поддерживается: таблица поддержки caniuse.com

На сегодняшний день, сентябрь 2018 г., Array.prototype.some () полностью поддерживается: таблица поддержки caniuse.com

jamess 15.09.2018 01:03

Работа в Node> = 8.10 для AWS Node.js Lambda, так что это здорово. Очень чистое и простое решение! ??

Jordan 21.09.2018 01:48

@jamess Возможно, он хорошо поддерживается, но помните, что Arrow functions в этом примере не так хорошо поддерживается. Подробнее см. Здесь: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Kamil Witkowski 24.01.2019 17:32

Есть короткое замыкание? Или он перебирает весь массив, даже если он нашел значение?

Douglas Gaskell 03.10.2019 03:06

@DouglasGaskell прерывает найденную итерацию (упоминается в ответе)

Michael 14.10.2019 15:28

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

/*
 * @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
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

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

при использовании es6 его можно сократить до contains = (a, obj) => a.some((element) => element === obj))

diEcho 28.05.2018 07:24

Даже IE9 поддерживает Array.prototype.some () начиная с ECMAScript 5.

Suncat2000 17.01.2019 20:45

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

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

Не поддерживается для IE и Microsfot Edge (2015) (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…‌)

Adriano Resende 06.11.2015 02:04

Также актуален Таблица совместимости ES7 (похоже, Chrome теперь поддерживает его)

styfle 11.03.2016 23:25

применимо ли это для проверки объекта? я не думаю, что это работает в случае объекта

Himesh Aadeshara 25.05.2018 07:18

Один лайнер:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
array.filter(e=>e==x).length > 0 эквивалентен array.some(e=>e==x), но some более эффективен
Apolo 22.04.2016 12:22

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

2015 г.

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

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

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

Я также предпочитаю whilefor, но не по какой-то конкретной причине я закончил писать функцию с помощью цикла 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

В качестве теста я создал массив из 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');

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

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

Используйте функцию 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)

Можно использовать Набор, у которого есть метод 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.info(contains(arr, 'Happy'));

Я думаю, что return proxy.has(obj) намного чище, чем две строки с выражением if-else здесь

Maciej Bukowski 19.08.2016 02:30
function contains(arr, obj) { return new Set(arr).has(obj); }
Gordon Bean 11.03.2020 18:48

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

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

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.info(['one', 'two'].exists('two'));

// Outputs -1
console.info(['one', 'two'].exists('three'));

console.info(['one', 'two', 'three', 'four'].exists('four'));

Что использовать, если не это?

bryc 20.02.2017 20:36

@bryc, возможно, принятое решение или другое решение отсюда. Если вам не важна производительность, вы можете использовать это

sqram 16.03.2017 22:49

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

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

это кажется запутанным. «объект» - плохое название, «предмет» могло бы быть лучше. логика функции фильтра должна просто возвращать currentObject === item; и тернарный оператор не нужен ..

TygerKrash 05.08.2016 14:15

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

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 с оптимизацией производительности. Спасибо поездка за указание на это.

Этот конкретный фрагмент кода может работать в IE6 (не тестировался), но IE не поддерживал ES5 до IE9.

Mark Reed 09.04.2017 15:51

По соображениям производительности вам следует избегать стягивания. По крайней мере, вам следует избегать JSON.stringify "obj" в каждом цикле, потому что это дорого и замедлит ваше приложение. Поэтому вы должны захватить его перед циклом for во временной переменной.

itinance 14.04.2017 11:45

@itinance хороший момент. Обновил функцию includes с учетом вашего предложения. Я запустил jsperf со своей функцией. Это примерно в 5 раз медленнее, чем у lodash. Хотя lodash не сравнивается по стоимости и не может найти {a: 1} в [{a: 1}]. Не знаю, делает ли это какая-нибудь библиотека. Но мне любопытно, есть ли еще эффективный и не безумно сложный способ сделать это.

Igor Barbashin 17.04.2017 07:57

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

Heretic Monkey 10.10.2019 18:10

@HereticMonkey, правда. Вот почему я добавил примечание sort-keys внизу

Igor Barbashin 16.10.2019 20:44

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

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

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

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

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

Heretic Monkey 10.10.2019 18:12

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

function include(arr,obj) { 
    return !!(~arr.indexOf(obj)); 
} 
  1. Либо используйте Array.indexOf(Object).
  2. С ECMA 7 можно использовать Array.includes(Object).
  3. С ECMA 6 вы можете использовать Array.find(FunctionName), где FunctionName - пользователь определенная функция для поиска объекта в массиве.

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

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

У него один параметр: массив номеров объектов. Каждый объект в массиве имеет два целочисленных свойства, обозначенных 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 } ];
var count = 0; 
var n = numbers.length;
for (var i =0;i<n;i++)
{
  if (numbers[i].x==numbers[i].y)
    {count+=1;}
}

alert(count);

Как бы вы сравнили значение x со значением x следующего элемента? Это не работает: for (var i = 0; i < n; i++) { if (numbers[i].x == (numbers[i] + 1).x) { count += 1; } }

armand 13.06.2018 16:32

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

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

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

Как он эффективнее? По крайней мере, вам нужно построить набор, который является На) (вам нужно выполнить итерацию по массиву). Простой линейный поиск (как это делает indexOf) - тоже На), но только в худшем случае. Средняя сложность случая больше похожа на п / 2, поскольку, если массив включает элемент, вы, скорее всего, остановитесь где-то посередине. Следовательно, этот метод в среднем медленнее, чем Array#includes и Array#indexOf.

Konstantin 30.03.2018 10:43

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

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

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

Simple solution : ES6 Features "includes" method

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

  arr.includes(2) // true

  arr.includes(93) // false

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

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, если ни один из элементов не соответствует данному условию.

Позднее примечание: это не работает, скажем, с contains([{ a: 1, b: 2 }], { b: 2, a: 1 }), потому что строковые объекты поддерживают порядок свойств.

Heretic Monkey 10.10.2019 18:12

    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.info(newArray);

Использование включает встроенную функцию javascript, но не работает в Internet Explorer

var optval = [];

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

Простое решение для этого требования - использование find().

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

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

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

let data = users.find(object => object['id'] === '104');

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

{id: "104", name: "admin"}

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

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.info(users);

вы получите значение, как показано ниже

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];

надеюсь, что это поможет кому-нибудь.

Представление

Сегодня, 2020.01.07, я провожу тесты на MacOs HighSierra 10.13.6 на Chrome v78.0.0, Safari v13.0.4 и Firefox v71.0.0 для 15 выбранных решений. Выводы

  • решения на основе JSON, Set и, что удивительно, find (K, N, O) самые медленные во всех браузерах
  • es6 includes (F) шустрый только на хроме
  • решения на основе for (C, D) и indexOf (G, H) довольно быстры во всех браузерах на малых и больших массивах, поэтому, вероятно, они являются лучшим выбором для эффективного решения
  • решения, в которых индекс уменьшается во время цикла, (B) медленнее, вероятно, из-за способа Кеш процессора работает.
  • Я также провожу тест для большого массива, когда искомый элемент находился на позиции 66% от длины массива, и решения на основе for (C, D, E) дают аналогичные результаты (~ 630 операций в секунду, но E в safari и firefox было 10 -20% медленнее, чем C и D)

Полученные результаты

Подробности

Я выполняю 2 тестовых случая: для массива с 10 элементами и массива с 1 миллионом элементов. В обоих случаях мы помещаем искомый элемент в середину массива.

let log = (name,f) => console.info(`${name}: 3-${f(arr,'s10')}  's7'-${f(arr,'s7')}  6-${f(arr,6)} 's3'-${f(arr,'s3')}`)

let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;

function A(a, val) {
    var i = -1;
    var n = a.length;
    while (i++<n) {
       if (a[i] === val) {
           return true;
       }
    }
    return false;
}

function B(a, val) {
    var i = a.length;
    while (i--) {
       if (a[i] === val) {
           return true;
       }
    }
    return false;
}

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

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

function E(a, val){  
  var n = a.length-1;
  var t = n/2;
  for (var i = 0; i <= t; i++) {
        if (a[i] === val || a[n-i] === val) return true;
  }
  return false;
}

function F(a,val) {
	return a.includes(val);
}

function G(a,val) {
	return a.indexOf(val)>=0;
}

function H(a,val) {
	return !!~a.indexOf(val);
}

function I(a, val) {
  return a.findIndex(x=> x==val)>=0;
}

function J(a,val) {
	return a.some(x=> x===val);
}

function K(a, val) {
  const s = JSON.stringify(val);
  return a.some(x => JSON.stringify(x) === s);
}

function L(a,val) {
	return !a.every(x=> x!==val);
}

function M(a, val) {
  return !!a.find(x=> x==val);
}

function N(a,val) {
	return a.filter(x=>x===val).length > 0;
}

function O(a, val) {
  return new Set(a).has(val);
}

log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!

Массив маленький - 10 элементов

Вы можете проводить тесты на своей машине ЗДЕСЬ

Массив большой - 1.000.000 элементов

Вы можете проводить тесты на своей машине ЗДЕСЬ

Object.keys для получения всех имен свойств объекта и фильтрации всех значений, которые полностью или частично совпадают с указанной строкой.

function filterByValue(array, string) {
  return array.filter(o =>
    Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}

const arrayOfObject = [{
  name: 'Paul',
  country: 'Canada',
}, {
  name: 'Lea',
  country: 'Italy',
}, {
  name: 'John',
  country: 'Italy'
}];

console.info(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.info(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]

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

Object.keys(o).some(k => o.country.toLowerCase().includes(string.toLowerCase())));

Теперь вы можете просто проверить количество массивов после фильтрации, чтобы проверить, содержит ли значение значение.

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

Добавление уникального элемента в другой список

searchResults: [
                {
                    name: 'Hello',
                    artist: 'Selana',
                    album: 'Riga',
                    id: 1,
                },
                {
                    name: 'Hello;s',
                    artist: 'Selana G',
                    album: 'Riga1',
                    id: 2,
                },
                {
                    name: 'Hello2',
                    artist: 'Selana',
                    album: 'Riga11',
                    id: 3,
                }
            ],
            playlistTracks: [
              {
                name: 'Hello',
                artist: 'Mamunuus',
                album: 'Riga',
                id: 4,
              },
              {
                name: 'Hello;s',
                artist: 'Mamunuus G',
                album: 'Riga1',
                id: 2,
              },
              {
                name: 'Hello2',
                artist: 'Mamunuus New',
                album: 'Riga11',
                id: 3,
              }
            ],
            playlistName: "New PlayListTrack",
        };
    }

    // Adding an unique track in the playList
    addTrack = track => {
      if (playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
        return;
      }
      playlistTracks.push(track);

      this.setState({
        playlistTracks
      })
    };

При чем здесь заданный вопрос?

stefanowiczp 06.02.2020 17:30

Используйте indexOf ()

Вы можете использовать метод indexOf (), чтобы проверить, существует ли данное значение или элемент в массиве или нет. Метод indexOf () возвращает индекс элемента внутри массива, если он найден, и возвращает -1, если он не найден. Давайте посмотрим на следующий пример:

var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
var a = "Mango";
checkArray(a, fruits);


function checkArray(a, fruits) {
  // Check if a value exists in the fruits array
  if (fruits.indexOf(a) !== -1) {
    return document.write("true");
  } else {
    return document.write("false");
  }
}

Используйте метод include ()

ES6 представил метод includes () для очень простого выполнения этой задачи. Но этот метод возвращает только истину или ложь вместо номера индекса:

var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
alert(fruits.includes("Banana")); // Outputs: true
alert(fruits.includes("Coconut")); // Outputs: false
alert(fruits.includes("Orange")); // Outputs: true
alert(fruits.includes("Cherry")); // Outputs: false

Для получения дополнительной информации см. здесь

Это может быть решение подробно и легко.

//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.info(check); //returns true
if (check)
{
   // value exists in array
   //write some codes
}

// array with objects
var arr = [
      {x:'a', y:'b'},
      {x:'p', y:'q'}
  ];

// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
    if (elm.x == 'p')
    {
       return elm; // returns length = 1 (object exists in array)
    }
});

// or y:'q' exists in arr
var check = arr.filter(function (elm){
    if (elm.y == 'q')
    {
       return elm; // returns length = 1 (object exists in array)
    }
});

// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
    if (elm.x == 'p' && elm.y == 'q')
    {
       return elm; // returns length = 1 (object exists in array)
    }
});

// in all cases
console.info(check.length); // returns 1

if (check.length > 0)
{
   // returns true
   // object exists in array
   //write some codes
}

используйте Array.prototype.includes, например:

const fruits = ['coconut', 'banana', 'apple']

const doesFruitsHaveCoconut = fruits.includes('coconut')// true

console.info(doesFruitsHaveCoconut)

возможно, прочтите эту документацию из MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

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

arrObj.findIndex(obj => obj === comparedValue) !== -1;

Возвращает true, если arrObj содержит compareValue, в противном случае - false.

Другие вопросы по теме