/
Вопросы и ответы
/
JavaScript
/

Как оставить в массиве только уникальные значения js

Как оставить в массиве только уникальные значения js

5 лет назад

Человек-Молекула

Ответы

7

Чтобы оставить в массиве только уникальные значения, воспользуемся таким лайфхаком:

1
2
3
4
const names = ['Karina', 'Ilona', 'Petr', 'Maks', 'Ilona', 'Maks'];
const uniqueNames = new Set(names); // создаём коллекцию уникальных значений
console.log(Array.from(uniqueNames)); // => [ 'Karina', 'Ilona', 'Petr', 'Maks' ]
// преобразуем в массив

Документация:

Set

4 года назад

Виктория Аблаева

6

Чтобы получить из массива уникальные значения, можно воспользоваться простым алгоритмом:

  1. Инициируем простой массив, в который будем складывать результат
  2. Проходимся по исходному массиву и на каждой итерации проверяем, если в результате еще нет текущего элемента, то добавляем его в результат.

Для реализации можно использовать либо цикл, либо встроенные методы для перебора массива, например reduce:

1
2
3
4
5
6
7
8
const items = ['item1', 'item2', 'item1', 'item3', 'item2', 'item4'];
const result = items.reduce((acc, item) => {
  if (acc.includes(item)) {
    return acc; // если значение уже есть, то просто возвращаем аккумулятор
  }
  return [...acc, item]; // добавляем к аккумулятору и возвращаем новый аккумулятор
}, []);
console.log(result); // => ['item1', 'item2', 'item3', 'item4']

5 лет назад

Ivan Gagarinov

5

Чтобы оставить в массиве только уникальные значения, можно воспользоваться методами filter() и indexOf():

1
2
3
4
5
6
7
const array = [1, 2, 1, 2, 3, 4, 5, 2, 4, 1, 1, 6];

const getUnique = (arr) => {
  return arr.filter((el, ind) => ind === arr.indexOf(el));
};

console.log(getUnique(array)); // => [ 1, 2, 3, 4, 5, 6 ]

Принцип работы заключается в том, что мы сравниваем индекс текущего элемента массива (ind) с индексом первого вхождения этого элемента в массив (arr.indexOf(el)). И если они не равны, то это означает, что вхождение данного элемента в массив является не первым, то есть элемент ранее уже встречался в массиве.

4 года назад

Кирилл Маркеев

3

По сути как первое решение, но чуть усовершенствованное. Работает на ВСЕХ типах, включая объекты и функции (но кроме null/false/undefined)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const options = [
	'Раз',
	2,
	3,
	true,
	(a, b) => a + b,
	4,
	'Раз',
	56,
	{ a: 1, b: 0 },
	3,
	2,
	(a, b) => a + b,
	'Раз',
	{ a: 1, b: 0 },
	1,
	false,
	false,
	true,
	(a, b) => a + b,
];


const getUniqueOptions = (options) => {
	return options.reduce(
		(res, cur) =>
			res.find((find) => JSON.stringify(find) === JSON.stringify(cur))
				? res
				: [...res, cur],
		[]
	).sort((a, b) => a - b); // и сортировочка для красоты :)
};

console.log(getUniqueOptions(options)); // ['Раз', 2, 3, true, ƒ, 4, 56, {…}, 1, false, false]

4 года назад

1
1
2
console.log(Array.from(new Set([1, 2, 1, 2, 3, 4, 5, 2, 4, 1, 1, 6]))) 
// [ 1, 2, 3, 4, 5, 6 ]

4 года назад

Виталий Меншиков

0

Уникальные значения массива оставляет Set — коллекция, которая хранит каждое значение один раз:

1
2
3
const numbers = [1, 2, 2, 3, 1, 4];
const unique = [...new Set(numbers)];
console.log(unique); // => [1, 2, 3, 4]

Порядок сохраняется: каждое значение остаётся на месте первого появления. То же самое: Array.from(new Set(numbers)).

Через filter

1
const unique = numbers.filter((n, i) => numbers.indexOf(n) === i);

Элемент остаётся, если его первое вхождение совпадает с текущей позицией. На больших массивах способ медленный: indexOf каждый раз проходит массив сначала. На массиве из десятков тысяч элементов разница с Set заметна.

Массив объектов

Set сравнивает объекты по ссылке, и два объекта с одинаковыми полями для него разные:

1
console.log(new Set([{ id: 1 }, { id: 1 }]).size); // => 2

Уникальные по полю id — через Map:

1
2
3
4
5
6
7
8
const users = [
  { id: 1, name: 'Анна' },
  { id: 2, name: 'Олег' },
  { id: 1, name: 'Анна' },
];

const uniqueUsers = [...new Map(users.map((u) => [u.id, u])).values()];
console.log(uniqueUsers.length); // => 2

Если id повторяется, в результате останется последний объект с этим id.

Без учёта регистра

1
2
3
4
5
6
7
8
9
const tags = ['JS', 'js', 'Python'];
const seen = new Set();
const uniqueTags = tags.filter((t) => {
  const key = t.toLowerCase();
  if (seen.has(key)) return false;
  seen.add(key);
  return true;
});
console.log(uniqueTags); // => ['JS', 'Python']

Только значения, которые встречаются один раз

Обратная задача — убрать всё, что повторяется:

1
2
const once = numbers.filter((n) => numbers.indexOf(n) === numbers.lastIndexOf(n));
console.log(once); // => [3, 4]

NaN

Set считает NaN равным NaN, а indexOf — нет. Поэтому filter с indexOf удалит из массива все NaN.

Коллекции и методы массивов разбирают в бесплатном курсе «Основы JavaScript».

7 дней назад

Никита Вихров

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845