Удалить дубликаты из массива в JavaScript
В этом посте мы обсудим, как удалить повторяющиеся значения из массива в JavaScript.
1. Использование Array.prototype.filter() функция
Простое решение — проверить второе вхождение для каждого элемента массива. Это можно легко сделать с помощью indexOf() метод с filter() метод следующим образом:
var arr = [ 1 , 3 , 5 , 1 , 2 , 3 , 7 , 4 , 5 ] ;
var unique = arr . filter ( ( x , i ) = > arr . indexOf ( x ) === i ) ;
console . log ( unique ) ;
результат: [ 1, 3, 5, 2, 7, 4 ]
2. Использование набора
Приведенное выше решение не рекомендуется из-за серьезных проблем с производительностью для больших массивов. Эффективным решением является преобразование массива в Set структуру данных, а затем преобразовать набор обратно в массив. Это решение работает как Set хранить уникальные значения и устраняет повторяющиеся значения. Обратите внимание, что это решение может изменить исходный порядок элементов, присутствующих в массиве.
Это может быть реализовано с помощью Set конструктор и Array.from() метод.
var arr = [ 1 , 3 , 5 , 1 , 2 , 3 , 7 , 4 , 5 ] ;
var unique = Array . from ( new Set ( arr ) ) ;
console . log ( unique ) ;
результат: [ 1, 3, 5, 2, 7, 4 ]
В качестве альтернативы вы можете использовать оператор Spread (. ) чтобы преобразовать набор обратно в массив.
Удаление повторяющихся объектов из массива JavaScript
Предположим, что у нас есть массив объектов, пример которого приведен ниже:
const books = [ < name: "My Sister the Serial Killer", author: "Oyinkan Braithwaite" >, < name: "Educated", author: "Tara Westover" >, < name: "My Sister the Serial Killer", author: "Oyinkan Braithwaite" >];
Первый и последний объект в массиве являются одинаковыми. Как удалить дубликаты из массива? На удивление, в 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) в массиве объектов всегда будет возвращать индекс переданного элемента, даже если там есть другой объект с одинаковыми свойствами и значениями.
Мое решение
Единственным способом сравнения объектов является проверка свойств и значений каждого из них. Поэтому решение заключается в ручной проверке. Механизм реализации:
- Проверять каждый элемент в массиве на соответствие последующему, который идет после него.
- Проверять только те элементы, которые не были определены как дубликаты другого элемента.
- Если значения каждого свойства объектов одинаковы, проверить, имеют ли объекты одинаковые ключи.
Финальная функция выглядит так:
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) »
Как удалить повторяющиеся элементы в массиве js
Если мы говорим о стандартных возможностях языка, можно удалить повторяющиеся элементы следующим образом:
const numbers = [-1, 3, 9, -9, 100, -100, 100, 100]; const newSet = new Set(numbers); // => Set(6) //new Set создаёт новую коллекцию, а нам нужен массив //воспользуемся методом Array.from(). Получаем: const uniqueNumbers = Array.from(newSet); // => [ -1, 3, 9, -9, 100, -100 ]
Массив с уникальными значениями готов!
16 ноября 2021
Чтобы удалить повторяющиеся элементы из массива, проще всего воспользоваться функцией uniq() из библиотеки ‘lodash’. Эта функция возвращает новый массив, из которого удалены все повторяющиеся элементы.
const uniqNumbers = _.uniq([2, 1, 2, 1]); console.log(uniqNumbers); // => [2, 1]
Как удалить повторяющиеся элементы массива в JavaScript?

5 простых способов удаления дубликатов элементов в массиве JavaScript.
Введение
Массивы являются одной из наиболее часто используемых структур данных в JavaScript. Часто массив может содержать дубликаты элементов, которые необходимо удалить для эффективной обработки данных. В этом блоге мы рассмотрим пять способов удаления дубликатов элементов в массиве с помощью JavaScript, ранжированных от наиболее эффективных до наименее эффективных.
1. Использование объекта Set
Объект Set является наиболее эффективным способом удаления дубликатов из массива в JavaScript. Это коллекция уникальных значений, что означает, что она автоматически удаляет дубликаты. Используя spread оператор, мы можем преобразовать объект Set обратно в массив, в результате чего получается массив, содержащий только уникальные значения. Вот пример:
const arr = [1, 1, 2, 2, 3, 4, 4, 5]; const uniqueArr = [. new Set(arr)]; console.log(uniqueArr); // [1, 2, 3, 4, 5]В этом примере мы сначала определяем массив с повторяющимися значениями. Затем мы создаем новый объект Set с помощью оператора spread ( . ). Наконец, мы снова преобразуем объект Set обратно в массив с помощью оператора spread. Результирующий массив содержит только уникальные значения.
2. Использование метода .filter
Метод .filter является вторым наиболее эффективным способом удаления дубликатов из массива в JavaScript. Он создает новый массив, который включает только элементы, отвечающие определенному условию, в данном случае элемент появляется в массиве только один раз. Вот пример:
const arr = [1, 1, 2, 2, 3, 4, 4, 5]; const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index); console.log(uniqueArr); // [1, 2, 3, 4, 5]В этом примере мы используем метод .filter для создания нового массива uniqueArr , который включает только элементы, удовлетворяющие условию внутри функции. Условие проверяет, равен ли индекс текущего элемента индексу его первого появления в массиве. Если это так, это означает, что элемент не является дубликатом и может быть включен в новый массив.
3. Использование метода .reduce
Метод .reduce немного менее эффективен, чем метод .filter . Он позволяет свести массив к одному значению, применив функцию к каждому элементу массива. В этом случае мы можем использовать .reduce для создания нового массива, включающего только уникальные значения. Вот пример:
const arr = [1, 1, 2, 2, 3, 4, 4, 5]; const uniqueArr = arr.reduce((acc, curr) => < if (!acc.includes(curr)) < acc.push(curr); >return acc; >, []); console.log(uniqueArr); // [1, 2, 3, 4, 5]В этом примере мы используем метод .reduce для итерации по каждому элементу массива и применяем функцию, которая проверяет, находится ли текущий элемент уже в массиве аккумулятора ( acc ). Если это не так, мы добавляем его в массив аккумулятора. Метод .reduce возвращает конечное значение массива аккумулятора, который является массивом, содержащим только уникальные значения.
4. Использование метода .forEach
Метод .forEach менее эффективен, чем предыдущие методы, но он по-прежнему является жизнеспособным вариантом. Он позволяет перебирать каждый элемент массива и применять к нему функцию. В этом случае мы можем использовать .forEach для создания нового массива, содержащего только уникальные значения. Вот пример:
const arr = [1, 1, 2, 2, 3, 4, 4, 5]; const uniqueArr = []; arr.forEach((item) => < if (!uniqueArr.includes(item)) < uniqueArr.push(item); >>); console.log(uniqueArr); // [1, 2, 3, 4, 5]В этом примере мы используем метод .forEach для итерации по каждому элементу массива и применения функции, которая проверяет, находится ли уже текущий элемент в массиве uniqueArr . Если это не так, мы добавляем его в массив uniqueArr . Результирующий массив содержит только уникальные значения.
5. Использование цикла for
Использование цикла for является наименее эффективным способом удаления дубликатов из массива. Он требует больше кода и вычислительной мощности, и он не такой лаконичный, как другие методы. Вот пример:
const arr = [1, 1, 2, 2, 3, 4, 4, 5]; const uniqueArr = []; for (let i = 0; i < arr.length; i++) < if (!uniqueArr.includes(arr[i])) < uniqueArr.push(arr[i]); >> console.log(uniqueArr); // [1, 2, 3, 4, 5]В этом примере мы используем цикл for для итерации по каждому элементу массива. Проверяем, есть ли текущий элемент в массиве uniqueArr . Если это не так, мы добавляем его в массив uniqueArr . Результирующий массив содержит только уникальные значения.
Итоги
Удаление дубликатов из массива является распространенной задачей в JavaScript. В этой статье мы рассмотрели пять различных способов выполнения этой задачи с помощью JavaScript. Каждый метод имеет свои преимущества и недостатки, поэтому вам решать, какой метод наилучшим образом соответствует вашим потребностям. Независимо от того, используется ли объект Set , метод .filter , метод .reduce , метод .forEach или цикл for , можно легко удалить дубликаты из массива и более эффективно обрабатывать данные.
Простая шина событий на JavaScript
8 месяцев назад · 3 мин. на чтение
Шины событий — это чрезвычайно полезный инструмент для разделения компонентов приложений.
Использование шины событий имеет свои плюсы и минусы. Поэтому она должна добавляться осторожно, иначе вы можете получить код, который будет трудно поддерживать и понимать. Но нет никаких сомнений в том, что шина событий может значительно ускорить процесс прототипирования или улучшить архитектуру малого и среднего приложения. Большому приложению могут потребоваться некоторые дополнительные инструменты и подходы. В этой статье рассмотрим как реализовать простую шину событий в JavaScript.
Что такое шина событий (event bus)?
Шина событий реализует шаблон издатель/подписчик. Его можно использовать для разъединения компонентов приложения, так что компонент может реагировать на события, инициируемые другим компонентом, без их прямых зависимостей друг от друга. Им нужно только знать шину событий. Каждый подписчик может подписаться на определенное событие. Подписчик будет уведомлен, когда событие, на которое он подписан, будет опубликовано в шине событий. Издатель может публиковать события в шине событий, когда что-то происходит.
Реализация шины событий
В этой реализации подписчик (subscriber) является простой функцией. Функция вызывается, когда интересующее событие публикуется в шине событий. Для сопоставления события с подписчиками можно использовать простой объект. Формат данных в этом объекте будет следующим: < eventType: < id: callback >> . Например:
< event1: < 1: func1, 2: func2 >, event2: < 3: func3 >>События event1 и event2 могут быть любого типа. В большинстве случаев имеет смысл использовать простые строки. Подписчики func1 , func2 и func3 являются простыми JavaScript функциями.
func1 и func2 являются подписчиками, подписанными на события типа event1 . func3 является подписчиком, подписанным на события типа event2 . Идентификаторы 1 , 2 и 3 будут использоваться позже для отмены подписки на подписчиков.Как подписаться на событие?
Функция subscribe принимает в качестве аргументов интересующее событие и подписчика. Функция возвращает объект, предоставляющий функцию отмены подписки - unsubscribe . Функция unsubscribe может быть вызвана для удаления зарегистрированного подписчика. В этом примере используем генератор id для получения уникальных идентификаторов.
Идентификаторы используются для быстрой идентификации (за время O(1)) подписчика при вызове функции unsubscribe . Вместо использования генератора id можно рассмотреть реализацию на основе ES6 символов.const subscriptions = <> const getNextUniqueId = getIdGenerator() function subscribe(eventType, callback) < const // создаем новый элемент для eventType if(!subscriptions[eventType]) < subscriptions[eventType] = <>> // регистрируем функцию обратного вызова subscriptions[eventType][id] = callback return < unsubscribe: () => < delete subscriptions[eventType][id] if(Object.keys(subscriptions[eventType]).length === 0) < delete subscriptions[eventType] >> > >Как опубликовать событие?
Функция публикации принимает в качестве аргументов событие и аргументы для подписчиков. Если подписчиков на eventType нет, то просто завершаем функцию. В противном случае перебираются идентификаторы подписчиков, зарегистрированных для eventType , и вызывается каждая функция с предоставленными аргументами.
function publish(eventType, arg) < if(!subscriptions[eventType]) < return >Object.keys(subscriptions[eventType]) .forEach(id => subscriptions[eventType][id](arg)) >Пример использования
В качестве простого примера предположим, что мы хотим печатать что-то в консоли каждый раз, когда появляется событие типа print . Мы можем подписаться на событие следующим образом:
const subscription = EventBus.subscribe( "print", message => console.log(`printing: $`) )Затем мы можем выпустить событие, подобное этому:
EventBus.publish("print", "some text")Если в какой-то момент мы захотим прекратить прослушивание события с типом print , мы можем отписаться следующим образом:
subscription.unsubscribe()Полная реализация
Вот полная реализация этой шины событий. Он может быть легко преобразован в простую функцию Javascript.
// eventBus.js const subscriptions = <> const getNextUniqueId = getIdGenerator() function subscribe(eventType, callback) < const if(!subscriptions[eventType]) < subscriptions[eventType] = <>> subscriptions[eventType][id] = callback return < unsubscribe: () => < delete subscriptions[eventType][id] if(Object.keys(subscriptions[eventType]).length === 0) < delete subscriptions[eventType] >> > > function publish(eventType, arg) < if(!subscriptions[eventType]) < return >Object.keys(subscriptions[eventType]).forEach(key => subscriptions[eventType][key](arg)) > function getIdGenerator() < let lastId = 0 return function getNextUniqueId() < lastId += 1 return lastId >> module.exports =
