Как проверить, встречаются ли все элементы одного массива в другом?
Что проверяют
Умеете ли вы оценить сложность решения и видите ли подводные камни сравнения в JavaScript. Решение через every и includes ждут за минуту, а дальше спрашивают, что будет на массивах в сто тысяч элементов и как быть с дубликатами и объектами.
Как отвечать
Покажите два решения и объясните, когда какое выбирать:
everyиincludes:a.every(x => b.includes(x)). Сложность O(n·m), зато без дополнительной памяти. Для массивов из десятков элементов этого достаточно;- через
Set:const s = new Set(b); a.every(x => s.has(x)). Построение множества O(m), проверки O(n) в среднем, итого O(n + m) по времени и O(m) по памяти; - встроенный метод:
new Set(a).isSubsetOf(new Set(b)). Методы множеств вошли в ES2025 и есть во всех актуальных браузерах, для старых окружений нужен полифилл.
Затем проговорите крайние случаи:
- пустой первый массив:
[].every(...)возвращаетtrue, и это верно, пустое множество входит в любое; - дубликаты: если
[1, 1]не должен считаться входящим в[1], множество не подходит. Нужен подсчёт черезMap: сколько раз каждое значение встречается во втором массиве, с уменьшением счётчика при проверке; - объекты:
includesиSetсравнивают по ссылке, два одинаковых по содержимому объекта различаются. Сравнивайте по ключу, например поid; NaN:includesиSetиспользуют алгоритм SameValueZero и находятNaN, аindexOfработает через строгое равенство и не находит.
Где спотыкаются
Путают направление и проверяют, что второй массив входит в первый. Стоит прямо сказать: «проверяю, что каждый элемент a есть в b».
Пишут filter(...).length === a.length. Это работает, но всегда проходит весь массив, а every останавливается на первом несовпадении.
Сортируют оба массива через sort() без компаратора. Он сравнивает элементы как строки, поэтому [10, 9, 1] превращается в [1, 10, 9], и к тому же мутирует исходные данные.