group_by và partition
Thuộc phần Logic và luồng xử lý trong hành trình Ruby của Coddy. Bài học 25 trên 56.
Đôi khi, bạn muốn chia một tập hợp thay vì lọc tập hợp đó. Hai phương thức đáp ứng hầu hết các trường hợp.
group_by nhận một khối lệnh và trả về một hash. Mỗi kết quả khác nhau từ khối lệnh sẽ trở thành một khóa, ánh xạ đến một mảng gồm các phần tử tạo ra kết quả đó:
words = ["hi", "hello", "yo", "hey", "bonjour"]
by_length = words.group_by { |w| w.length }
puts by_length.inspect
# {2=>["hi", "yo"], 5=>["hello"], 3=>["hey"], 7=>["bonjour"]}Đây là cách gọn nhất để phân nhóm các phần tử chỉ trong một lượt.
partition là phiên bản nhị phân: nó trả về một cặp mảng, gồm các phần tử mà khối lệnh cho kết quả đúng và các phần tử còn lại:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect # [2, 4]
puts odds.inspect # [1, 3, 5]Dùng partition khi có đúng hai nhóm, dùng group_by khi có thể có nhiều nhóm.
Thử thách
Trung bìnhĐọc danh sách các mục name:score được phân tách bằng dấu phẩy (ví dụ: Alice:88,Bob:42,Charlie:75). Dùng group_by rồi đến partition để tạo một báo cáo ngắn.
Các bước:
- Phân tích từng mục thành một cặp
[name, score](score là số nguyên) - Dùng
group_byđể nhóm các cặp theo chữ cái đầu tiên củaname(chữ hoa) - Với mỗi nhóm chữ cái, theo thứ tự bảng chữ cái, dùng
partitionđể chia các mục thành nhóm đạt (score >= 60) và nhóm không đạt, sau đó in một dòng cho mỗi nhóm:
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>Trong mỗi nhóm, tên giữ nguyên thứ tự ban đầu. Nếu một nhóm không có tên nào, hãy để trống (ví dụ: fail=).
Với đầu vào Alice:88,Adam:42,Bob:75,Beth:55,Cara:90, đầu ra là:
A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=Tự làm thử
entries = gets.chomp.split(",").map do |s|
name, score = s.split(":")
[name, score.to_i]
end
# TODO: nhóm theo chữ cái đầu tiên (viết hoa), chia mỗi nhóm theo điều kiện score >= 60,
# in ra 'X: pass=... fail=...' theo thứ tự bảng chữ cái
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 xử lý
1Tìm hiểu sâu về chuỗi
Tổng quan về phương thức chuỗiNội suy chuỗiDuyệt qua chuỗiTách và nối chuỗiÔn tập: Đan chuỗi4Khối lệnh, Proc và lambda
Khối lệnh là gì?do..end và dấu ngoặc nhọnTừ khóa yieldTham số của khối lệnhProc và lambdaÔn tập: bộ lặp tùy chỉnh7Hash, phần 2
Hash.new với giá trị mặc địnhLặp qua HashHash lồng nhauGộp và chuyển đổiÔn tập: Bộ đếm tần suất10Dự án: Hồ sơ học sinh
Tổng quan dự ánThêm học sinh2Phạm vi
Phạm vi là gì?Các phương thức của phạm viPhạm vi trong case / whenÔn tập: luyện tập với phạm vi5Sức mạnh của Enumerable
select và rejectNối chuỗi mapreduce / injectcount, all?, any?, none?group_by và partitionsort_by, min_by, max_byÔn tập: quy trình dữ liệuTự luyện tập: Trình biên dịch Ruby online