Каждый из нас рано или поздно сталкивается с необходимостью избавиться от дубликатов в массиве. Для кого-то это проблема, для кого-то — обычное дело. Эта короткая статья предназначена для того, чтобы сделать своих читателей членами второй категории. Итак, давайте начнем.

Конструктор Set()

Пожалуй, самый простой способ удалить дубликаты из массива — использовать конструктор Set(). Конструктор Set() принимает итерируемый объект в качестве первого параметра, а затем создает на его основе набор уникальных элементов. Если параметры отсутствуют, создается пустой набор.

Итак, давайте объявим и инициализируем массив a, состоящий из шести элементов.

const a = [1, 2, 3, 3, 2, 1];

Как мы видим, уникальными элементами здесь являются 1, 2 и 3. Давайте воспользуемся конструктором Set(), чтобы увидеть это.

const uniqueSet = new Set(a);
console.log(uniqueSet); // Set(3) {1, 2, 3};

Теперь, чтобы снова отформатировать наш набор в массив, мы можем использовать метод Array.prototype.from() с передачей uniqueSet в качестве параметра.

console.log(Array.from(uniqueSet)) // [1, 2, 3]

Показатели производительности: ~0,008 мс

Массив.прототип.фильтр()

Решение с Array.prototype.filter() — это цикл по исходному массиву со сравнением индексов на каждой его итерации. Чтобы быть точным, мы сравниваем индекс текущей итерации с результатом вызова Array.prototype.indexOf() для текущего элемента. Из-за того, что Array.prototype.indexOf() останавливается на первом совпадении, в результирующий массив не попадут дубликаты элемента. Код выглядит так.

const a = [1, 2, 3, 3, 2, 1];
const unique = a.filter((item, index) => index === a.indexOf(item));
console.log(unique); // [1, 2, 3]

Показатели производительности: ~0,06 мс

Массив.прототип.уменьшить()

В решении проблемы может быть полезен Array.prototype.reduce() метод. Таким образом, мы просто строим результирующий массив, добавляя элемент итерации, если он еще не включен.

const a = [1, 2, 3, 3, 2, 1];
const unique = a.reduce(
  (uniqueArray, item) => uniqueArray.includes(item)
    ? uniqueArray
    : [...uniqueArray, item],
  [],
)
console.log(unique);

Показатели производительности: ~0,065 мс

Интересно отметить, что мы можем отказаться от деструктуризации и вместо этого использовать метод Array.prototype.push(). В этом случае код будет чуть более громоздким, но в то же время его выполнение займет меньше времени. Честно говоря, чуть меньше.

Объект.keys()

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

const a = [1, 2, 3, 3, 2, 1];
let uniqueKeys = {};
for (let i = 0; i < a.length; i += 1) {
  uniqueKeys[a[i]] = true;
}

Затем получаем ключи объекта и формируем из них результирующий массив.

console.log(Object.keys(uniqueKeys)) // [1, 2, 3]

Показатели производительности: ~0,012 мс

Заключение

Если мы захотим, мы можем найти много способов решить эту проблему. Единственный вопрос — зачем? Как мы видим, использование встроенного конструктора Set() показывает лучшую производительность, чем любой из перечисленных вариантов. В то же время этот способ наиболее лаконичен. С другой стороны, конструктор Set() может не подходить для особых случаев, поэтому знание других опций является хорошим преимуществом.