Thêm phần tử vào tập hợp
Thuộc phần Logic và luồng điều khiển trong hành trình GO của Coddy. Bài học 33 trên 68.
Giờ đây, khi đã tạo một tập hợp (set), bước tiếp theo là học cách thêm phần tử vào đó. Vì tập hợp trong Go thực chất được tạo từ một map, nên thêm phần tử vào tập hợp cũng giống hệt như thêm khóa vào map.
Để thêm một phần tử vào tập hợp, bạn chỉ cần gán giá trị struct rỗng cho một khóa mới:
colors["yellow"] = struct{}{}Cú pháp struct{}{} tạo một giá trị struct rỗng. struct{} đầu tiên chỉ định kiểu, còn {} thứ hai khởi tạo giá trị đó. Đây là cách tiêu chuẩn để thêm phần tử vào tập hợp trong Go.
Điểm hay của cách này là nếu bạn thử thêm lại cùng một phần tử, nó chỉ ghi đè lên mục hiện có, giúp tập hợp giữ được tính duy nhất.
Lưu ý rằng struct{}{} là cú pháp hợp lệ duy nhất cho phép gán này: chỉ viết {} mà không có tên kiểu sẽ gây ra lỗi biên dịch: thiếu kiểu trong biểu thức khởi tạo tổ hợp. Bạn luôn phải ghi rõ kiểu khi gán giá trị cho khóa của map bên ngoài một biểu thức khởi tạo map.
Thêm phần tử vào tập hợp rất nhanh và đơn giản. Cách này tận dụng cách triển khai map hiệu quả của Go, đồng thời giúp bạn theo dõi các phần tử duy nhất như một tập hợp thực thụ.
Thử thách
DễXây dựng hệ thống theo dõi kỹ năng để quản lý năng lực kỹ thuật của nhà phát triển bằng thành ngữ tập hợp của Go. Thử thách này hướng dẫn cách thêm kỹ năng mới vào tập hợp, đồng thời ngăn trùng lặp và theo dõi tiến độ học tập.
Bạn sẽ nhận được hai đầu vào:
- Một chuỗi biểu thị số kỹ năng dự kiến (ví dụ:
"5"), chỉ dùng để tham khảo - Một chuỗi chứa các kỹ năng, ngăn cách bằng dấu phẩy (ví dụ:
"Go,Docker,Kubernetes,Go,React,Docker,Python")
Nhiệm vụ của bạn là:
- Tạo một tập hợp bằng thành ngữ Go
map[string]struct{}để lưu các kỹ năng kỹ thuật không trùng lặp - Khởi tạo tập hợp với ba kỹ năng ban đầu:
"Programming","Problem Solving"và"Communication" - Phân tích chuỗi đầu vào bằng cách tách chuỗi tại các dấu phẩy để lấy tên từng kỹ năng
- Xử lý TẤT CẢ kỹ năng trong chuỗi được phân tách bằng dấu phẩy (duyệt toàn bộ lát cắt, không dùng tham số số lượng)
- Với mỗi kỹ năng trong đầu vào, thêm kỹ năng đó vào tập hợp bằng cách dùng
struct{}{}làm giá trị - Hiển thị kết quả xử lý bằng cách in từng kỹ năng khi xử lý:
- Nếu kỹ năng chưa có trong tập hợp:
"Learning new skill: [skill]" - Nếu kỹ năng đã có trong tập hợp:
"Already mastered: [skill]"
- Nếu kỹ năng chưa có trong tập hợp:
- Sau khi xử lý tất cả kỹ năng, hiển thị bản tóm tắt tiến độ:
"Skills processed: [total_processed]", dùng độ dài của lát cắt kỹ năng"New skills learned: [new_skills_count]""Total skills mastered: [total_unique_skills]"
- Cuối cùng, liệt kê tất cả kỹ năng trong tập hợp kỹ năng của nhà phát triển:
- Tiêu đề:
"Complete skill set:" - Mỗi kỹ năng nằm trên một dòng riêng:
"✓ [skill]"
- Tiêu đề:
Quan trọng: Dùng range để duyệt tất cả kỹ năng trong lát cắt, không dùng tham số số lượng. Số lượng chỉ để tham khảo, không nên dùng để kiểm soát vòng lặp. Dùng gói strings để tách chuỗi đầu vào. Để kiểm tra kỹ năng đã tồn tại trước khi thêm, hãy dùng thành ngữ comma ok: _, exists := skillSet[skill]. Thử thách này minh họa cách thêm phần tử vào tập hợp Go tự động loại bỏ trùng lặp, đồng thời cho phép tra cứu nhanh khi kiểm tra phần tử có thuộc tập hợp hay không.
Tự làm thử
package main
import (
"fmt"
"sort"
"strconv"
"strings"
)
func main() {
// Đọc đầu vào
var countStr string
var skillsStr string
fmt.Scanln(&countStr)
fmt.Scanln(&skillsStr)
// Chuyển chuỗi count thành số nguyên (chỉ để tham khảo, không dùng trong vòng lặp)
_, _ = strconv.Atoi(countStr)
// Khởi tạo tập hợp kỹ năng với các kỹ năng ban đầu
skillSet := map[string]struct{}{
"Programming": struct{}{},
"Problem Solving": struct{}{},
"Communication": struct{}{},
}
// Tách chuỗi skills thành từng kỹ năng
skills := strings.Split(skillsStr, ",")
// TODO: Viết code bên dưới
// Xử lý từng kỹ năng bằng range để duyệt qua TẤT CẢ kỹ năng trong slice
// Dùng cách viết comma ok: _, exists := skillSet[skill]
// Thêm kỹ năng mới bằng: skillSet[skill] = struct{}{}
// Hiển thị kết quả xử lý của từng kỹ năng
// Tính và hiển thị tóm tắt tiến độ bằng len(skills)
// Liệt kê mọi kỹ năng trong tập hợp đầy đủ (cân nhắc sắp xếp để đầu ra nhất quán)
}Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Logic và luồng điều khiển
1Luồng điều khiển nâng cao
Switch với `fallthrough`Thoát khỏi vòng lặp lồng nhauTiếp tục một vòng lặp cụ thểCâu lệnh `goto`Ôn tập: điều khiển vòng lặp nâng cao4Dự án: Danh sách việc cần làm đơn giản
Thiết lập dự ánThêm một việc cần làm2Struct và phương thức
Định nghĩa phương thức cho structReceiver giá trịReceiver con trỏChọn receiverPhương thức và hàmÔn tập: hành vi của struct5Tìm hiểu chuyên sâu về map
Map chứa structCon trỏ làm giá trị của mapKiểm tra map nilSo sánh các mapÔn tập: bộ đếm tần suất từ8Dự án: Quản lý hàng tồn kho đơn giản
Tổng quan dự ánKiểm tra hàng tồn kho3Interface (cơ bản)
Interface là gì?Định nghĩa interfaceTriển khai interfaceDùng kiểu interfaceInterface rỗngKhẳng định kiểuType switchÔn tập: hình dạng và hành vi6Go theo cách viết thành ngữ: tập hợp
Cách dùng tập hợp trong GoTạo tập hợpThêm phần tử vào tập hợpKiểm tra phần tử có thuộc tập hợp khôngXóa phần tử khỏi tập hợpLặp qua tập hợpÔn tập: tên người dùng duy nhấtTự luyện tập: Trình biên dịch Go online