Удаление дубликатов из массива JavaScript: методы для примитивов и объектов

Дубликаты в массивах мешают аналитике и приводят к неверным расчётам - особенно когда речь о примитивах и объектах с одинаковыми полями. В статье показаны методы: Set для примитивов, filter и reduce для кастомных условий, а также подходы для массивов объектов с сохранением нужных полей и предсказуемой сложности.

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

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

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

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

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)»

Комментарии

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

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

И
Иван

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