Удаление повторяющихся объектов из массива JavaScript

Дубли в массиве могут нарушить логику работы приложения и снизить производительность. Особенно это актуально для сложных данных, таких как объекты. Разберемся, как эффективно удалять повторяющиеся элементы без потери информации.

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

Наталья Кайдаавтор материала

Удаление дубликатов из одномерных массивов (легкий способ)

Предположим, что у нас есть массив строк:

const strings = [
    "My Sister the Serial Killer", 
    "Educated", 
    "My Sister the Serial Killer"
];

Чтобы удалить повторяющиеся элементы из такого массива, можно использовать метод filter() вместе с методом indexOf(). Он позволяет проверить, не повторяется ли какой-либо из элементов.

const filteredStrings = strings.filter((item, index) => {

    // Возврат к новому массиву, если индекс текущего элемента
//совпадает с другим

return strings.indexOf(item) === index;

});

strings.indexOf(item) всегда будет возвращать индекс первого вхождения элемента, мы можем выяснить, является ли текущий элемент повторяющимся в фильтрующей цикле. Если да, мы не возвращаем его в новый массив, созданный методом filter().

Объекты не работают одинаково

Этот способ не подходит для сравнения объектов. В JavaScript любые два объекта с одинаковыми свойствами и значениями не считаются одинаковыми.

const a = {
    name: "My Sister the Serial Killer",  
    author: "Oyinkan Braithwaite" 
};
const b = {
    name: "My Sister the Serial Killer
",  
    author: "Oyinkan Braithwaite" 
};

a === b // false

В JavaScript объекты имеют ссылочный тип. Поэтому равными будут только ссылки на один и тот же объект. Таким образом, indexOf(object) в массиве объектов всегда будет возвращать индекс переданного элемента, даже если там есть другой объект с одинаковыми свойствами и значениями.

Мое решение

Единственным способом сравнения объектов является проверка свойств и значений каждого из них. Поэтому решение заключается в ручной проверке. Механизм реализации:

  1. Проверять каждый элемент в массиве на соответствие последующему, который идет после него.
  2. Проверять только те элементы, которые не были определены как дубликаты другого элемента.
  3. Если значения каждого свойства объектов одинаковы, проверить, имеют ли объекты одинаковые ключи.

Финальная функция выглядит так:

function removeDuplicates(arr) {

    const result = [];
    const duplicatesIndices = [];

    // Перебираем каждый элемент в исходном массиве
    arr.forEach((current, index) => {
    
        if (duplicatesIndices.includes(index)) return;
    
        result.push(current);
    
        // Сравниваем каждый элемент в массиве после текущего
        for (let comparisonIndex = index + 1; comparisonIndex < arr.length; comparisonIndex++) {
        
            const comparison = arr[comparisonIndex];
            const currentKeys = Object.keys(current);
            const comparisonKeys = Object.keys(comparison);
            
            // Проверяем длину массивов
            if (currentKeys.length !== comparisonKeys.length) continue;
            
            // Проверяем значение ключей
            const currentKeysString = currentKeys.sort().join("").toLowerCase();
            const comparisonKeysString = comparisonKeys.sort().join("").toLowerCase();
            if (currentKeysString !== comparisonKeysString) continue;
            
            // Проверяем индексы ключей
            let valuesEqual = true;
            for (let i = 0; i < currentKeys.length; i++) {
                const key = currentKeys[i];
                if ( current[key] !== comparison[key] ) {
                    valuesEqual = false;
                    break;
                }
            }
            if (valuesEqual) duplicatesIndices.push(comparisonIndex);
            
        } // Конец цикла
    });  
    return result;
}

Наталья Кайдаавтор-переводчик статьи «Removing duplicate objects from an Array (is hard)»

Комментарии

Оставьте свой комментарий
И
Иван

Работает исправно и без внесения правок. Сэкономлено несколько @опочасов 😉

И
Иван

Безграничное спасибо за функцию!