Первоначально опубликовано в Блоге Уилла

При работе с массивами значений в 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, и мы можем быть уверены, что исходный массив не содержит повторяющихся значений!

Мне очень нравится второй подход за его лаконичность и выразительность, но вы можете столкнуться с проблемами поддержки браузера, если вам нужно настроить таргетинг на более старые браузеры, так что примите это во внимание!