Cách sử dụng tập hợp (Set) trong JavaScript

Javascript căn bản | by Học Javascript

Trong JavaScript, Set là một cấu trúc dữ liệu đặc biệt giúp lưu trữ danh sách các giá trị duy nhất, tức là không có phần tử trùng lặp. Không giống như Array, Set không cho phép hai phần tử có cùng giá trị, giúp tối ưu hóa hiệu suất trong nhiều trường hợp như lọc dữ liệu trùng lặp hoặc tìm kiếm nhanh hơn.

Vậy Set hoạt động như thế nào? Khi nào nên sử dụng Set thay vì Array? Trong bài viết này, mình sẽ tìm hiểu chi tiết về cách tạo, thao tác, duyệt và ứng dụng thực tế của Set trong lập trình JavaScript.

Set trong JavaScript

Set là một đối tượng trong JavaScript được sử dụng để lưu trữ tập hợp các giá trị duy nhất, nghĩa là không có phần tử nào bị trùng lặp. Set có thể chứa bất kỳ loại dữ liệu nào, từ số, chuỗi, đối tượng đến các kiểu dữ liệu phức tạp khác.

Set giúp tối ưu hiệu suất khi làm việc với danh sách dữ liệu cần loại bỏ các phần tử trùng lặp hoặc khi cần kiểm tra sự tồn tại của một giá trị một cách nhanh chóng.

Ví dụ tạo một Set:

const mySet = new Set([1, 2, 3, 3, 4, 5]);  
console.log(mySet); // Output: Set { 1, 2, 3, 4, 5 } (phần tử 3 bị loại bỏ vì trùng lặp)

Sự khác biệt giữa Set và Array

Tiêu chí Set Array
Lưu trữ giá trị Chỉ chứa các giá trị duy nhất, không trùng lặp Có thể chứa giá trị trùng lặp
Truy cập phần tử Không hỗ trợ truy cập phần tử bằng chỉ mục (index) Có thể truy cập phần tử bằng chỉ mục (array[index])
Hiệu suất tìm kiếm Tìm kiếm nhanh hơn do sử dụng cấu trúc bảng băm Tìm kiếm chậm hơn nếu duyệt qua toàn bộ mảng
Duyệt phần tử Sử dụng forEach(), for...of hoặc values() Sử dụng forEach(), for...of, map(), v.v.
Loại bỏ phần tử trùng lặp Tự động loại bỏ phần tử trùng lặp Cần kiểm tra và loại bỏ thủ công

Ví dụ về sự khác biệt:

const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueSet = new Set(arr);
console.log([...uniqueSet]); // Output: [1, 2, 3, 4, 5] (chuyển Set thành mảng)

Khi nào nên sử dụng Set thay vì Array?

  • Khi cần lưu trữ danh sách không trùng lặp: Nếu bạn cần một danh sách mà mỗi phần tử xuất hiện duy nhất, Set là lựa chọn tối ưu thay vì Array.
  • Khi cần kiểm tra nhanh một giá trị có tồn tại hay không: Set có hiệu suất kiểm tra sự tồn tại của phần tử tốt hơn Array do sử dụng bảng băm.
  • Khi muốn loại bỏ trùng lặp từ một danh sách nhanh chóng: Chuyển đổi một mảng thành Set giúp loại bỏ các phần tử trùng lặp một cách dễ dàng.
  • Khi không cần truy cập phần tử bằng chỉ mục: Nếu bạn cần truy xuất phần tử dựa trên vị trí, hãy sử dụng Array thay vì Set.

Ví dụ thực tế:

const emails = ["[email protected]", "[email protected]", "[email protected]", "[email protected]"];
const uniqueEmails = new Set(emails);
console.log([...uniqueEmails]); // Output: ['[email protected]', '[email protected]', '[email protected]']

Khởi tạo và sử dụng Set trong JavaScript

Cách tạo một Set bằng new Set()

Trong JavaScript, Set là một đối tượng được sử dụng để lưu trữ các giá trị duy nhất, tức là không có phần tử nào bị trùng lặp.

Để tạo một Set, ta sử dụng từ khóa new Set() như sau:

const mySet = new Set(); // Tạo một Set rỗng
console.log(mySet); // Output: Set(0) {}

Ngoài ra, ta cũng có thể khởi tạo một Set với một mảng hoặc một tập hợp các giá trị ban đầu:

const numbers = new Set([1, 2, 3, 4, 5]);
console.log(numbers); // Output: Set(5) { 1, 2, 3, 4, 5 }
Nếu trong mảng có các giá trị trùng lặp, Set sẽ tự động loại bỏ chúng:
const duplicateNumbers = new Set([1, 2, 2, 3, 4, 4, 5]);
console.log(duplicateNumbers); // Output: Set(5) { 1, 2, 3, 4, 5 }

Thêm phần tử vào Set bằng .add()

Để thêm phần tử vào một Set, ta sử dụng phương thức .add(value). Nếu giá trị đã tồn tại, Set sẽ không thêm trùng lặp.

Cú pháp:

setObject.add(value);

Ví dụ:

const mySet = new Set();
mySet.add(10);
mySet.add(20);
mySet.add(30);
mySet.add(10); // Giá trị 10 đã tồn tại, sẽ không được thêm lại

console.log(mySet); // Output: Set(3) { 10, 20, 30 }

Bạn cũng có thể thêm các kiểu dữ liệu khác như chuỗi, object, hoặc mảng vào Set:

const mixedSet = new Set();
mixedSet.add("Hello");
mixedSet.add({ name: "Alice" });
mixedSet.add([1, 2, 3]);

console.log(mixedSet);
// Output: Set(3) { 'Hello', { name: 'Alice' }, [ 1, 2, 3 ] }

Lưu ý:

  • Khi thêm object hoặc array vào Set, chúng không được xem là giống nhau ngay cả khi chúng có nội dung tương tự. Vì mỗi object hoặc array có một tham chiếu bộ nhớ riêng biệt.

Ví dụ:

const setExample = new Set();
setExample.add({ a: 1 });
setExample.add({ a: 1 });

console.log(setExample.size); // Output: 2 (Dù có cùng nội dung, chúng là hai object khác nhau)

Ví dụ minh họa về cách khởi tạo và thêm phần tử vào Set

Dưới đây là một ví dụ đầy đủ về cách tạo và thêm phần tử vào Set:

const fruits = new Set();

// Thêm phần tử vào Set
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Apple"); // Apple đã tồn tại nên sẽ không được thêm lại

console.log(fruits); // Output: Set(3) { 'Apple', 'Banana', 'Orange' }

// Kiểm tra số lượng phần tử trong Set
console.log(fruits.size); // Output: 3

Ví dụ trên cho thấy Set giúp loại bỏ các phần tử trùng lặp một cách tự động.

Các phương thức cơ bản của Set trong JavaScript

Đối tượng Set trong JavaScript cung cấp nhiều phương thức hữu ích để thao tác với tập hợp dữ liệu. Dưới đây là những phương thức cơ bản cùng với ví dụ minh họa chi tiết.

add(value): Thêm giá trị vào Set

Phương thức .add(value) dùng để thêm một giá trị mới vào Set. Nếu giá trị đã tồn tại, nó sẽ không được thêm lại.

Cú pháp:

setObject.add(value);
Ví dụ:
const mySet = new Set();
mySet.add(1);
mySet.add(2);
mySet.add(2); // Giá trị 2 đã tồn tại nên không được thêm lại
mySet.add(3);

console.log(mySet); // Output: Set(3) { 1, 2, 3 }

delete(value): Xóa một giá trị khỏi Set

Phương thức .delete(value) được sử dụng để xóa một giá trị cụ thể khỏi Set.

Cú pháp:

setObject.delete(value);

Ví dụ:

const numbers = new Set([1, 2, 3, 4, 5]);

numbers.delete(3); // Xóa giá trị 3 khỏi Set
console.log(numbers); // Output: Set(4) { 1, 2, 4, 5 }

// Xóa một giá trị không tồn tại
console.log(numbers.delete(10)); // Output: false

Phương thức delete() trả về true nếu xóa thành công, ngược lại trả về false.

has(value): Kiểm tra giá trị có tồn tại trong Set không

Phương thức .has(value) dùng để kiểm tra xem một giá trị có tồn tại trong Set hay không.

Cú pháp:

setObject.has(value);

Ví dụ:

const fruits = new Set(["Apple", "Banana", "Orange"]);

console.log(fruits.has("Banana")); // Output: true
console.log(fruits.has("Mango"));  // Output: false

.size: Trả về số lượng phần tử trong Set

Thuộc tính .size giúp đếm số lượng phần tử hiện có trong Set.

Cú pháp:

setObject.size;

Ví dụ:

const colors = new Set(["Red", "Green", "Blue"]);

console.log(colors.size); // Output: 3

colors.add("Yellow");
console.log(colors.size); // Output: 4

Không giống như mảng (Array), Set không có phương thức .length, mà thay vào đó sử dụng .size để đếm số phần tử.

clear(): Xóa toàn bộ phần tử trong Set

Phương thức .clear() dùng để xóa tất cả phần tử trong Set, giúp làm rỗng tập hợp.

Cú pháp:

setObject.clear();

Ví dụ:

const mySet = new Set([1, 2, 3, 4, 5]);

console.log(mySet.size); // Output: 5

mySet.clear(); // Xóa toàn bộ phần tử
console.log(mySet.size); // Output: 0
console.log(mySet); // Output: Set(0) {}

Ví dụ tổng hợp sử dụng các phương thức của Set

Dưới đây là một chương trình sử dụng các phương thức add(), delete(), has(), size, và clear() trong Set:

const mySet = new Set();

// Thêm phần tử vào Set
mySet.add("JavaScript");
mySet.add("Python");
mySet.add("C++");

console.log(mySet); // Output: Set(3) { 'JavaScript', 'Python', 'C++' }
console.log("Số lượng phần tử:", mySet.size); // Output: 3

// Kiểm tra sự tồn tại của một phần tử
console.log("Có JavaScript không?", mySet.has("JavaScript")); // Output: true
console.log("Có Ruby không?", mySet.has("Ruby")); // Output: false

// Xóa một phần tử
mySet.delete("Python");
console.log(mySet); // Output: Set(2) { 'JavaScript', 'C++' }

// Xóa toàn bộ phần tử
mySet.clear();
console.log(mySet); // Output: Set(0) {}
console.log("Số lượng phần tử:", mySet.size); // Output: 0

Phương thức / Thuộc tính Chức năng
add(value) Thêm giá trị vào Set, không thêm trùng lặp.
delete(value) Xóa một giá trị cụ thể khỏi Set.
has(value) Kiểm tra xem một giá trị có tồn tại trong Set hay không.
size Trả về số lượng phần tử có trong Set.
clear() Xóa tất cả các phần tử trong Set.

Duyệt qua Set trong JavaScript

Khi làm việc với Set, chúng ta có thể duyệt qua các phần tử bên trong nó bằng nhiều cách khác nhau. Dưới đây là các phương pháp phổ biến:

  • Dùng vòng lặp for...of
  • Dùng phương thức .forEach()

Dùng vòng lặp for...of để duyệt Set

Vòng lặp for...of là cách đơn giản và phổ biến để duyệt qua từng phần tử của Set.

Cú pháp:

for (let value of setObject) {
    // Thực hiện xử lý với value
}

Ví dụ:

const mySet = new Set(["Apple", "Banana", "Cherry"]);

for (let fruit of mySet) {
    console.log(fruit);
}

Kết quả:

Apple
Banana
Cherry

Vòng lặp for...of duyệt qua từng phần tử trong Set mà không cần truy cập theo chỉ mục (do Set không có chỉ mục như Array).

Dùng phương thức .forEach() để duyệt Set

Ngoài for...of, chúng ta có thể sử dụng phương thức .forEach() để duyệt qua từng phần tử trong Set.

Cú pháp:

setObject.forEach((value) => {
    // Xử lý từng phần tử
});

Ví dụ:

const mySet = new Set(["Red", "Green", "Blue"]);

mySet.forEach((color) => {
    console.log(color);
});

Kết quả:

Red
Green
Blue

Phương thức .forEach() hoạt động tương tự như khi dùng với Array, nhưng do Set không có chỉ mục, nên tham số thứ hai (index) của .forEach() sẽ nhận giá trị giống với tham số đầu tiên (value).

So sánh for...of và .forEach() khi duyệt Set

Phương pháp Ưu điểm Nhược điểm
for...of Ngắn gọn, dễ đọc, có thể dùng break hoặc continue để kiểm soát vòng lặp. Không có tham số thứ hai để truy cập index (vì Set không có index).
.forEach() Duyệt qua từng phần tử một cách dễ dàng, có thể viết dạng hàm mũi tên. Không thể dùng break hoặc continue, không thể dừng vòng lặp sớm.

Ví dụ nâng cao: Kết hợp Set với vòng lặp

Ví dụ 1: Duyệt qua Set và lọc dữ liệu

const numbers = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

for (let num of numbers) {
    if (num % 2 === 0) {
        console.log(`Số chẵn: ${num}`);
    }
}

Kết quả:

Số chẵn: 2
Số chẵn: 4
Số chẵn: 6
Số chẵn: 8
Số chẵn: 10
Ví dụ 2: Dùng .forEach() để hiển thị danh sách tên
const names = new Set(["Alice", "Bob", "Charlie"]);

names.forEach((name) => {
    console.log(`Xin chào, ${name}!`);
});
Kết quả:
Xin chào, Alice!
Xin chào, Bob!
Xin chào, Charlie!

Chuyển đổi giữa SetArray

SetArray là hai cấu trúc dữ liệu quan trọng trong JavaScript. Trong nhiều trường hợp, chúng ta cần chuyển đổi qua lại giữa chúng để tận dụng các ưu điểm của từng loại.

Chuyển từ Set sang Array

Do Set không có chỉ mục như Array, chúng ta có thể chuyển đổi nó thành một mảng để dễ thao tác hơn bằng cách sử dụng:

  • Sử dụng Array.from(set)
  • Sử dụng toán tử spread [...]

Ví dụ: Chuyển Set thành Array

const mySet = new Set(["Apple", "Banana", "Cherry"]);

// Cách 1: Dùng Array.from()
const arrayFromSet = Array.from(mySet);
console.log(arrayFromSet); // ["Apple", "Banana", "Cherry"]

// Cách 2: Dùng toán tử spread [...]
const arraySpread = [...mySet];
console.log(arraySpread); // ["Apple", "Banana", "Cherry"]

Khi nào cần chuyển từ Set sang Array?

  • Khi cần sử dụng các phương thức của Array như .map(), .filter(), .reduce(), v.v.
  • Khi cần truy cập phần tử theo chỉ mục (Set không hỗ trợ truy cập theo chỉ mục).

Chuyển từ Array sang Set để loại bỏ phần tử trùng lặp

Một trong những ứng dụng phổ biến nhất của Set là loại bỏ phần tử trùng lặp trong mảng.

Ví dụ: Loại bỏ phần tử trùng lặp trong mảng

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

// Chuyển đổi Array thành Set để loại bỏ trùng lặp
const uniqueNumbers = new Set(numbers);
console.log(uniqueNumbers); // Set { 1, 2, 3, 4, 5, 6, 7 }

// Chuyển lại thành Array nếu cần
const uniqueArray = [...uniqueNumbers];
console.log(uniqueArray); // [1, 2, 3, 4, 5, 6, 7]

Ứng dụng thực tế của Set trong lập trình

Loại bỏ phần tử trùng lặp trong mảng

Như đã đề cập, chúng ta có thể dùng Set để lọc ra các phần tử duy nhất trong mảng.

Ví dụ: Loại bỏ email trùng lặp trong danh sách

const emails = [
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]"
];

const uniqueEmails = [...new Set(emails)];
console.log(uniqueEmails);
// ["[email protected]", "[email protected]", "[email protected]"]

Lưu trữ danh sách các giá trị duy nhất

Set hữu ích khi cần lưu trữ dữ liệu mà không muốn trùng lặp, chẳng hạn như danh sách ID hoặc người dùng đã đăng nhập.

Ví dụ: Lưu danh sách người dùng trực tuyến

const onlineUsers = new Set();

onlineUsers.add("Alice");
onlineUsers.add("Bob");
onlineUsers.add("Charlie");
onlineUsers.add("Alice"); // Không bị thêm vào lần nữa

console.log(onlineUsers); // Set { 'Alice', 'Bob', 'Charlie' }

Kết bài

Set trong JavaScript là một cấu trúc dữ liệu mạnh mẽ giúp lưu trữ các giá trị duy nhất một cách hiệu quả. Với các phương thức linh hoạt như .add(), .delete(), .has(), và khả năng chuyển đổi dễ dàng giữa SetArray, nó mang lại nhiều lợi ích trong việc xử lý dữ liệu.

So với Array, Set có hiệu suất tốt hơn khi cần loại bỏ phần tử trùng lặp hoặc kiểm tra sự tồn tại của phần tử. Nhờ đó, nó được sử dụng rộng rãi trong các tình huống như quản lý danh sách ID duy nhất, xử lý dữ liệu văn bản, hoặc tối ưu hóa tìm kiếm.

Bằng cách tận dụng Set đúng cách, bạn có thể viết code ngắn gọn, hiệu quả và tối ưu hơn trong các ứng dụng JavaScript thực tế.

Bài viết liên quan

  • 2