Удаление дубликатов из массива объектов в JavaScript
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Для удаления повторений в массиве объектов можно применить сочетание методов filter()
и findIndex()
. Следующий пример поможет сохранить лишь первое появление объекта в массиве основываясь на уникальном ключе. В данном коде мы фильтруем объекты по их id
:
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()
. Но стоит помнить, что этот подход может быть весьма затратным для больших объемов данных:
const unique = items.filter((obj, idx, arr) =>
arr.findIndex(t => JSON.stringify(t) === JSON.stringify(obj)) === idx);
Обратите внимание: при использовании JSON.stringify()
критически важно сохранение порядка свойств объектов. Если порядок изменяется, рассмотрите возможность использования более продвинутых способов сравнения.
Создание полезных утилит
Для удобства поиска дубликатов можно создать функцию isPropValuesEqual
, которая будет проверять равенство заданных свойств объектов:
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
, которая динамически помогает избавиться от дубликатов, основываясь на выбранных свойствах:
function getUniqueItemsByProperties(items, props) {
return items.filter((item, index, self) =>
index === self.findIndex(t => isPropValuesEqual(t, item, props)));
}
// Ваша команда будет в восторге 🍾🥂
Использование возможностей ES6+ и Map
С появлением ES6 был введён Map
, который идеально подходит для создания коллекций с уникальными ключами:
// Начинаем процесс 🦄
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
:
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()
:
// Проявляем изобретательность с помощью `Set` и `map()` 🕵️♀️
const unique = Array.from(new Set(items.map(item => JSON.stringify(item)))).map(item => JSON.parse(item));
Оставайтесь в курсе любых технологических новинок. Чтобы сохранить последний экземпляр повторяющихся элементов, используйте метод findLastIndex
вместо findIndex
.
Полезные материалы
- Array.prototype.filter() – MDN — Интегрируйте
filter()
в свой инструментарий для устранения повторов в массивах. - Array.prototype.reduce() – MDN — Освойте техники агрегированной обработки данных через
reduce()
. - Array.prototype.map() – MDN — Трансформируйте массивы и избавьтесь от дубликатов с помощью
map()
. - Set – MDN — Применяйте
Set
для создания коллекций с уникальными элементами в JavaScript. - Destructuring assignment – MDN — Изучите деструктуризацию для эффективной обработки данных.
- JSON.stringify() – MDN — Познакомьтесь с
JSON.stringify()
для выполнения глубокого сравнения объектов. - Lodash Documentation — Облегчите себе обработку массивов с помощью функции uniqWith от Lodash.