3.1.  Линейный («обычный») поиск

Найти что-то в массиве — довольно частая задача. Это может быть поиск целого объекта по его признаку: например, найти полный объект банковской карточки из списка сохранённых, зная только её id/номер. Или просто проверка на вхождение: к примеру, чтобы узнать, можно ли показывать определённый контент пользователю, можно проверять его права в системе в массиве разрешающих просмотр прав.

Самый простой и распространённый способ поиска в массивах и других коллекциях — линейный поиск. Это довольно «глупый» алгоритм, который просто перебирает все элементы до тех пор, пока не встретит нужный нам или не дойдёт до конца массива. Например, у нас есть массив из запрещённых для постов слов: ['Спотти', 'Персик', 'котик']. И нам надо проверить, запрещено ли слово 'Кекс'. Сначала мы посмотрим на 'Спотти' и сравним его с искомым словом. Они не равны, поэтому двигаемся дальше — к слову 'Персик'. С ним и с 'котик'-ом ситуация такая же: сравнение их с 'Кекс'-ом вернёт нам false. А затем мы придём в конец массива. Это значит, искомого элемента в нём нет, можно постить! Алгоритмическую сложность подобных алгоритмов, которые перебирают все элементы из массива, мы уже знаем — это O(n). (А сколько займёт прогон через такой список запрещённых слов поста из m слов?)

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

В JavaScript есть несколько способов нахождения искомого в массивах. Уверены, вы пользовались всеми или почти всеми из них, но давайте их вспомним.

Проверка на вхождение с помощью includes

Если элемент у нас уже есть и нам надо только проверить, есть ли он в массиве, стоит использовать includes. Пример сверху можно переписать вот так:

const forbiddenWords = ['Спотти', 'Персик', 'котик'];

function checkIfForbidden(word) {
  return forbiddenWords.includes(word);
}

checkIfForbidden('Кекс'); // false

includes

Поиск одного элемента с find или нескольких — с filter

Например, если у нас есть список зарегистрированных на мероприятие участников:

const participants = [
  {
    id: 1,
    name: 'Иван Иванов',
    meal: 'regular', // Предпочтения в еде, либо веган, либо нет
  },
  {
    id: 2,
    name: 'Игорь Николаев',
    meal: 'vegan',
  },
  {
    id: 3,
    name: 'Павел Константинов',
    meal: 'regular',
  }
]

И мы хотим достать оттуда одного «целого» участника, зная только его id, то наш выбор — find. Он вернёт только первый элемент, который подходит под наше условие:

const firstParticipant = participants.find(({id}) => id === 1);

А если нам нужно достать несколько участников, например, всех веганов, то нужно использовать filter:

const vegans = participants.filter(({meal}) => meal === 'vegan');

filter

Поиск индекса элемента в массиве с помощью findIndex и indexOf

Бывают случаи, когда нам нужен не сам элемент массива, а только его индекс. Например, чтобы удалить его потом из массива по найденному индексу. findIndex работает, как и find: принимает аргументом функцию для поиска (её ещё называют «предикат») и возвращает индекс первого найденного элемента или -1, если такого не нашлось.

const pashaIndex = participants.findIndex(({name}) => name === 'Павел Константинов'); // 2

А indexOf принимает аргументом уже сам элемент, а не предикат, и также возвращает либо его индекс, либо -1, если его нет внутри.

const firstIndex = participants.indexOf(firstParticipant);

indexOf/findIndex