logo

Удаление дубликатов из массива объектов в JavaScript

Быстрый ответ

Для удаления повторений в массиве объектов можно применить сочетание методов filter() и findIndex(). Следующий пример поможет сохранить лишь первое появление объекта в массиве основываясь на уникальном ключе. В данном коде мы фильтруем объекты по их id:

JS
Скопировать код
const items = [{ id: 1 }, { id: 2 }, { id: 1 }];
// Применяем магию JavaScript 🧙‍♂️
const unique = items.filter((obj, idx, arr) => 
  idx === arr.findIndex((t) => t.id === obj.id));
console.log(unique); // Вывод: [{ id: 1 }, { id: 2 }]
// Клонирование побеждено 👯‍♂️

Глубокое сравнение объектов

Рассмотрим более сложный вариант. Для глубокого сравнения объектов может быть полезно использовать JSON.stringify(). Но стоит помнить, что этот подход может быть весьма затратным для больших объемов данных:

JS
Скопировать код
const unique = items.filter((obj, idx, arr) => 
  arr.findIndex(t => JSON.stringify(t) === JSON.stringify(obj)) === idx);

Обратите внимание: при использовании JSON.stringify() критически важно сохранение порядка свойств объектов. Если порядок изменяется, рассмотрите возможность использования более продвинутых способов сравнения.

Создание полезных утилит

Для удобства поиска дубликатов можно создать функцию isPropValuesEqual, которая будет проверять равенство заданных свойств объектов:

JS
Скопировать код
function isPropValuesEqual(obj1, obj2, props) {
  // Подготавливаемся к проверке 🔥
  return props.every(prop => obj1[prop] === obj2[prop]);
}

const unique = items.filter((obj, idx, arr) =>
  idx === arr.findIndex(t => isPropValuesEqual(t, obj, ['name', 'place'])));
// Теперь вы с лёгкостью найдёте дубликат 👀

Также будет полезна функция getUniqueItemsByProperties, которая динамически помогает избавиться от дубликатов, основываясь на выбранных свойствах:

JS
Скопировать код
function getUniqueItemsByProperties(items, props) {
  return items.filter((item, index, self) =>
    index === self.findIndex(t => isPropValuesEqual(t, item, props)));
}
// Ваша команда будет в восторге 🍾🥂

Использование возможностей ES6+ и Map

С появлением ES6 был введён Map, который идеально подходит для создания коллекций с уникальными ключами:

JS
Скопировать код
// Начинаем процесс 🦄
const uniqueItems = [...new Map(items.map(item => [JSON.stringify(item), item])).values()];

Создав новую карту с уникальными ключами-строками, а затем превращая итератор .values() в массив, мы элегантно избавляемся от повторов.

Визуализация

Визуализируем процесс удаления повторений в массиве объектов:

Исходный массив 📦Уникальный массив 🏆
Объект A, Объект B, Объект A,
Объект C, Объект B, Объект C

Процесс фильтрации (🔍):

ШагДействие
Обнаружение повторов (🔍)Определяем Объекты A, B и C как повторы
Удаление повторов (🗑️)Оставляем одну копию каждого из объектов A, B и C
Сбор уникальных элементов (🏆)В уникальном массиве по одному экземпляру из каждого объекта A, B, C

Продолжайте борьбу с дубликатами, пока в вашем распоряжении не окажутся только уникальные элементы.

Составные ключи и высокая производительность

Если столкнулись со сложностью в обеспечении уникальных идентификаторов, можно использовать составные ключи, которые можно создать с помощью функции objToId:

JS
Скопировать код
function objToId(obj, props) {
  // Формируем составные ключи 👷‍♀️
  return props.map(prop => obj[prop]).join('_');
}

const unique = [...new Map(items.map(item => [objToId(item, ['name', 'place']), item])).values()];
// Вы — мастер создания ключей 🔐

Если ценно сохранить исходный порядок элементов, остерегайтесь методов, основанных на Map. Старайтесь избегать JSON.stringify() для работы с большими массивами данных из-за отрицательных эффектов на производительность. При работе со сложными структурами данных расмотрите использование внешних библиотек для облегчения процесса.

Бонус: Современные методы для обеспечения уникальности

Не забывайте про Set, впрочем он не идеален для работы с уникальными объектами. Тут может пригодиться комбинация Set и метода map():

JS
Скопировать код
// Проявляем изобретательность с помощью `Set` и `map()` 🕵️‍♀️
const unique = Array.from(new Set(items.map(item => JSON.stringify(item)))).map(item => JSON.parse(item));

Оставайтесь в курсе любых технологических новинок. Чтобы сохранить последний экземпляр повторяющихся элементов, используйте метод findLastIndex вместо findIndex.

Полезные материалы

  1. Array.prototype.filter() – MDN — Интегрируйте filter() в свой инструментарий для устранения повторов в массивах.
  2. Array.prototype.reduce() – MDN — Освойте техники агрегированной обработки данных через reduce().
  3. Array.prototype.map() – MDN — Трансформируйте массивы и избавьтесь от дубликатов с помощью map().
  4. Set – MDN — Применяйте Set для создания коллекций с уникальными элементами в JavaScript.
  5. Destructuring assignment – MDN — Изучите деструктуризацию для эффективной обработки данных.
  6. JSON.stringify() – MDN — Познакомьтесь с JSON.stringify() для выполнения глубокого сравнения объектов.
  7. Lodash Documentation — Облегчите себе обработку массивов с помощью функции uniqWith от Lodash.