← Назад к вопросам
Удалите дубликаты из массива
1.8 Middle🔥 131 комментариев
#Node.js и JavaScript#Алгоритмы и структуры данных
Условие
Напишите функцию removeDuplicates(arr), которая удаляет дубликаты из массива. Реализуйте несколько способов:
function removeDuplicatesSet(arr) {
// С помощью Set
}
function removeDuplicatesFilter(arr) {
// С помощью filter
}
function removeDuplicatesReduce(arr) {
// С помощью reduce
}
const arr = [1, 2, 2, 3, 4, 4, 5, 1];
console.log(removeDuplicatesSet(arr)); // [1, 2, 3, 4, 5]
Дополнительно
Как удалить дубликаты объектов по определенному полю?
Что проверяется
- Знание разных подходов
- Работа с Set
- Методы массивов
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Удаление дубликатов из массива
1. С помощью Set (оптимально)
function removeDuplicatesSet<T>(arr: T[]): T[] {
return Array.from(new Set(arr));
// или
// return [...new Set(arr)];
}
const arr = [1, 2, 2, 3, 4, 4, 5, 1];
console.log(removeDuplicatesSet(arr)); // [1, 2, 3, 4, 5]
Плюсы: O(n) время, O(n) память, сохраняет порядок, очень быстро
Минусы: Сравнивает по ===, проблема с объектами и NaN
2. С помощью filter и indexOf
function removeDuplicatesFilter<T>(arr: T[]): T[] {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
const arr = [1, 2, 2, 3, 4, 4, 5, 1];
console.log(removeDuplicatesFilter(arr)); // [1, 2, 3, 4, 5]
Плюсы: Простой, читаемый код, работает с любыми типами
Минусы: O(n²) время, медленнее на больших массивах
3. С помощью reduce
function removeDuplicatesReduce<T>(arr: T[]): T[] {
return arr.reduce((acc: T[], item: T) => {
if (!acc.includes(item)) {
acc.push(item);
}
return acc;
}, []);
}
const arr = [1, 2, 2, 3, 4, 4, 5, 1];
console.log(removeDuplicatesReduce(arr)); // [1, 2, 3, 4, 5]
Плюсы: Функциональный стиль, контролируемый процесс
Минусы: O(n²) из-за includes, медленнее
4. С помощью Object/Map (O(n))
function removeDuplicatesMap<T>(arr: T[]): T[] {
const seen = new Map<T, boolean>();
return arr.filter(item => {
if (seen.has(item)) {
return false;
}
seen.set(item, true);
return true;
});
}
const arr = [1, 2, 2, 3, 4, 4, 5, 1];
console.log(removeDuplicatesMap(arr)); // [1, 2, 3, 4, 5]
Плюсы: O(n) время, хороший контроль над логикой
Минусы: Чуть более громоздкий код
5. Удаление дубликатов объектов по полю
Способ 1: По уникальному ID
interface User {
id: number;
name: string;
email: string;
}
function removeDuplicatesByKey<T>(arr: T[], key: keyof T): T[] {
const seen = new Set();
return arr.filter(item => {
const value = item[key];
if (seen.has(value)) {
return false;
}
seen.add(value);
return true;
});
}
const users: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
{ id: 1, name: 'Alice 2', email: 'alice2@example.com' }, // дубликат по id
{ id: 3, name: 'Carol', email: 'carol@example.com' }
];
const unique = removeDuplicatesByKey(users, 'id');
// [
// { id: 1, name: 'Alice', email: 'alice@example.com' },
// { id: 2, name: 'Bob', email: 'bob@example.com' },
// { id: 3, name: 'Carol', email: 'carol@example.com' }
// ]
Способ 2: По кастомной функции
function removeDuplicatesByFn<T>(
arr: T[],
fn: (item: T) => any
): T[] {
const seen = new Set();
return arr.filter(item => {
const key = fn(item);
if (seen.has(key)) {
return false;
}
seen.add(key);
return true;
});
}
// По email
const uniqueByEmail = removeDuplicatesByFn(
users,
user => user.email.toLowerCase()
);
// По комбинации полей
const uniqueByCombo = removeDuplicatesByFn(
users,
user => `${user.id}-${user.email}`
);
Способ 3: С использованием Map для максимума/минимума
// Оставляем последний элемент с дубликатом
function removeDuplicatesKeepLast<T>(arr: T[], key: keyof T): T[] {
const map = new Map<any, T>();
arr.forEach(item => {
map.set(item[key], item); // перезаписываем, остаётся последний
});
return Array.from(map.values());
}
// Оставляем первый элемент
function removeDuplicatesKeepFirst<T>(arr: T[], key: keyof T): T[] {
const map = new Map<any, T>();
arr.forEach(item => {
const k = item[key];
if (!map.has(k)) {
map.set(k, item); // устанавливаем только если нет
}
});
return Array.from(map.values());
}
6. Обработка специальных случаев
NaN
// Set обрабатывает NaN корректно
const arrWithNaN = [1, NaN, 2, NaN, 3];
console.log([...new Set(arrWithNaN)]); // [1, NaN, 2, 3] ✓
// filter + indexOf НЕ работает (NaN !== NaN)
console.log(arrWithNaN.filter((v, i) => arrWithNaN.indexOf(v) === i));
// [1, NaN, 2, NaN, 3] ✗ NaN не удалён
// Решение: кастомная функция
const uniqueWithNaN = arr.filter((v, i, a) => {
if (Number.isNaN(v)) {
return !a.slice(0, i).some(Number.isNaN);
}
return a.indexOf(v) === i;
});
Строки (case-insensitive)
function removeDuplicatesCaseInsensitive(arr: string[]): string[] {
const seen = new Set();
return arr.filter(item => {
const lower = item.toLowerCase();
if (seen.has(lower)) {
return false;
}
seen.add(lower);
return true;
});
}
const words = ['hello', 'HELLO', 'Hello', 'world'];
console.log(removeDuplicatesCaseInsensitive(words)); // ['hello', 'world']
7. Сравнение производительности
const largeArr = Array(100000).fill(0).map(() => Math.floor(Math.random() * 10000));
console.time('Set');
const r1 = [...new Set(largeArr)];
console.timeEnd('Set'); // ~5ms
console.time('filter + indexOf');
const r2 = largeArr.filter((v, i, a) => a.indexOf(v) === i);
console.timeEnd('filter + indexOf'); // ~5000ms ❌
console.time('Map');
const seen = new Map();
const r3 = largeArr.filter(v => {
if (seen.has(v)) return false;
seen.set(v, true);
return true;
});
console.timeEnd('Map'); // ~3ms
8. Рекомендации
| Сценарий | Метод | Причина |
|---|---|---|
| Примитивы, простой случай | Set | O(n), встроенный, быстро |
| Объекты по ID | Set + key | O(n), простой API |
| Объекты по кастом функции | Map + filter | O(n), гибкий |
| Учить собеседование | Все варианты | Показывает знания |
| Production код | Set или Map | Производительность |
9. Тестирование
test('removeDuplicatesSet', () => {
expect(removeDuplicatesSet([1, 2, 2, 3, 4])).toEqual([1, 2, 3, 4]);
});
test('removeDuplicatesFilter', () => {
expect(removeDuplicatesFilter([1, 2, 2, 3, 4])).toEqual([1, 2, 3, 4]);
});
test('removeDuplicatesByKey', () => {
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice2' }
];
const result = removeDuplicatesByKey(users, 'id');
expect(result).toHaveLength(2);
});
test('removeDuplicatesWithNaN', () => {
const arr = [1, NaN, 2, NaN, 3];
const result = [...new Set(arr)];
expect(result).toHaveLength(4);
});