Lấy giá trị duy nhất từ mảng với Set
Cách hiện đại và hiệu quả nhất (ES6) là dùng Set - cấu trúc dữ liệu chỉ lưu giá trị duy nhất.
Ví dụ minh họa
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Unique Array Values</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; }
.result, .sample { font-size: 18px; font-weight: 500; color: rebeccapurple; font-family: monospace; }
.result { color: red; }
button { padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<h1>Lấy giá trị duy nhất trong mảng</h1>
<div class="sample"></div>
<div class="result"></div>
<button class="btn-demo">LOẠI BỎ TRÙNG LẶP</button>
<h3>Nhấn nút để xóa giá trị trùng lặp khỏi mảng</h3>
<script>
const resultEle = document.querySelector(".result");
const sampleEle = document.querySelector(".sample");
const btn = document.querySelector(".btn-demo");
const arr = [2, 3, 4, 2, 3, 4, "A", "A", "B", "B"];
sampleEle.textContent = "Mảng gốc: " + JSON.stringify(arr);
btn.addEventListener("click", () => {
// Cách 1: Set + Spread operator (ES6) - NGẮN GỌN NHẤT
const unique = [...new Set(arr)];
resultEle.textContent = "Unique (Set + spread): " + JSON.stringify(unique);
// Cách 2: Array.from()
resultEle.textContent += "\nArray.from: " + JSON.stringify(Array.from(new Set(arr)));
// Cách 3: filter + indexOf (ES5, chậm O(n²))
const uniqueOld = arr.filter((val, idx) => arr.indexOf(val) === idx);
resultEle.textContent += "\nFilter indexOf: " + JSON.stringify(uniqueOld);
// Cách 4: reduce (ES5)
const uniqueReduce = arr.reduce((acc, val) => {
if (!acc.includes(val)) acc.push(val);
return acc;
}, []);
resultEle.textContent += "\nReduce: " + JSON.stringify(uniqueReduce);
});
</script>
</body>
</html>
So sánh hiệu suất
| Phương pháp | Độ phức tạp | Hỗ trợ | Khuyến nghị |
|---|---|---|---|
[...new Set(arr)] | O(n) | ES6+ | ✓ Tốt nhất |
Array.from(new Set(arr)) | O(n) | ES6+ | Tốt |
filter + indexOf | O(n²) | ES5 | Tránh (mảng lớn) |
reduce + includes | O(n²) | ES5 | Tránh (mảng lớn) |
for loop + object map | O(n) | ES5 | OK nếu không dùng Set |
Unique cho mảng Object (theo property)
const users = [
{ id: 1, name: 'An' },
{ id: 2, name: 'Bình' },
{ id: 1, name: 'An (dup)' },
{ id: 3, name: 'Cường' }
];
// Unique theo id
const uniqueById = [...new Map(users.map(u => [u.id, u])).values()];
// [{id:1,name:'An'}, {id:2,name:'Bình'}, {id:3,name:'Cường'}]
// Unique theo nhiều property (composite key)
const uniqueByNameAge = [...new Map(
users.map(u => [`${u.name}|${u.age}`, u])
).values()];
Unique giữ nguyên thứ tự (Set tự động giữ thứ tự insertion)
const arr = [3, 1, 2, 3, 1, 4];
[...new Set(arr)]; // [3, 1, 2, 4] - giữ thứ tự xuất hiện đầu tiên
Polyfill Set cho IE11
if (typeof Set === 'undefined') {
// Simple polyfill hoặc dùng core-js
// Hoặc dùng object map cho ES5:
function unique(arr) {
const seen = {};
return arr.filter(item => {
const key = typeof item + ':' + JSON.stringify(item);
if (seen[key]) return false;
seen[key] = true;
return true;
});
}
}