Первоначально опубликовано в Блоге Уилла
При работе с массивами значений в JavaScript мы иногда хотим определить, содержит ли массив повторяющиеся значения. К сожалению, массивы JavaScript не предоставляют никаких встроенных методов, которые могли бы сделать это за нас — мы должны сами написать реализацию.
Один из подходов к этой проблеме может выглядеть так:
function checkForDuplicates(array) { let valuesAlreadySeen = []
for (let i = 0; i < array.length; i++) { let value = array[i] if (valuesAlreadySeen.indexOf(value) !== -1) { return true } valuesAlreadySeen.push(value) } return false }
Это работает, но в худшем случае, когда единственное повторяющееся значение находится в конце массива, это не очень эффективный подход. Нам пришлось бы перебирать весь массив (который может быть огромным!) только для того, чтобы в последнем элементе понять, что на самом деле в массиве есть неуникальное значение.
Другой подход, который я недавно изучил, использует мощь наборов ES6.
Если вы не знакомы с наборами в JavaScript (я не был знаком до недавнего времени!), вот определение MDN:
Объекты
Set
представляют собой наборы значений. Вы можете перебирать элементы набора в порядке вставки. Значение вSet
может встречаться только один раз; он уникален в коллекцииSet
.
Прочтите последнюю строчку еще раз, так как это наш секретный соус. ‘Значение в Set
может встречаться только один раз; он уникален в коллекции Set
.
Этот факт означает, что мы можем преобразовать исходный массив в Set
, а затем быть уверенными, что он содержит только уникальные значения. Как только мы извлекли все уникальные значения из массива и сохранили их в нашем Set
, мы можем сравнить длины массива и набора. Если длины не совпадают, из этого должно следовать, что массив содержит повторяющиеся значения!
Вот как выглядит этот подход:
function checkForDuplicates(array) {
return new Set(array).size !== array.length
}
Если длина Set
и массива не совпадают, эта функция вернет true
, указывая на то, что массив содержит дубликаты. В противном случае, если массив и Set
имеют одинаковую длину, функция вернет false
, и мы можем быть уверены, что исходный массив не содержит повторяющихся значений!
Мне очень нравится второй подход за его лаконичность и выразительность, но вы можете столкнуться с проблемами поддержки браузера, если вам нужно настроить таргетинг на более старые браузеры, так что примите это во внимание!