Hôm nay chúng ta sẽ nói về slice_before
, slice_when
và slice_after
. Đây là những phương thức siêu hữu ích khi bạn cần nhóm các mục trong một mảng hoặc các kiểu liệt kê khác dựa trên các tiêu chí tùy ý.
Có thể bạn đã quen thuộc với Array#slice
. Nó cho phép bạn lấy ra một tập hợp con của một mảng dựa trên một loạt các chỉ số:
a = ["a", "b", "c"]
a.slice(1, 2)
# => ["b", "c"]
Điều này rất hữu ích, nhưng nó không thể được sử dụng với liệt kê, vì liệt kê không có chỉ số.
slice_before
, slice_when
và slice_after
các phương thức không dựa vào chỉ số - vì vậy bạn có thể sử dụng chúng với bất kỳ phương thức nào. Hãy cùng xem!
Sử dụng Enumerable#slice_before
Enumerable#slice_before
chia nhỏ và liệt kê thành các nhóm tại thời điểm trước khi trận đấu được thực hiện.
Trận đấu được thực hiện thông qua ===
toán tử, có nghĩa là bạn có thể kết hợp tất cả các loại thứ.
Giá trị phù hợp
Bạn có thể khớp với một giá trị duy nhất. Đó là điều hiển nhiên. :)
a = ["a", "b", "c"]
a.slice_before("b").to_a
# => [["a"], ["b", "c"]]
Đối sánh Cụm từ Thông dụng
Bạn có thể sử dụng biểu thức chính quy để đối sánh văn bản phức tạp hơn.
a = ["000", "b", "999"]
a.slice_before(/[a-z]/).to_a
# => [["000"], ["b", "999"]]
Đối sánh phạm vi
Nếu bạn đang làm việc với các số, bạn có thể phân chia mảng dựa trên một phạm vi.
a = [100, 200, 300]
a.slice_before(150..250).to_a
# => [[100], [200, 300]]
Đối sánh lớp
Điều này có vẻ hơi lạ đối với bạn, nhưng nó hoàn toàn phù hợp với hành vi của ===
nhà điều hành.
a = [1, "200", 1.3]
a.slice_before(String).to_a
# => [[1], ["200", 1.3]]
Sử dụng một khối
Nếu không có tùy chọn nào khác đủ linh hoạt để bạn luôn có thể tìm thấy đối sánh theo lập trình với một khối.
a = [1, 2, 3, 4, 5]
a.slice_before do |item|
item % 2 == 0
end
# => [[1], [2, 3], [4, 5]]
Sử dụng Enumerable#slice_after
Enumerable#slice_after
hoạt động chính xác như Enumerable#slice_before
ngoại trừ việc lát cắt xảy ra sau trận đấu. Đi tìm con số. :-)
a = ["a", "b", "c"]
a.slice_after("b").to_a
# => [["a", "b"], ["c"]]
Tất nhiên, bạn có thể so khớp bằng cách sử dụng biểu thức chính quy, phạm vi và khối. Tôi sẽ không đưa ra các ví dụ về những điều đó ở đây vì nó sẽ rất tẻ nhạt.
Sử dụng Enumerable#slice_when
Enumerable#slice_when
là một con thú khác với slice_before
và slice_after
. Thay vì so khớp một mục duy nhất trong mảng, bạn so khớp một cặp mục liền kề.
Điều này có nghĩa là bạn có thể nhóm các mục dựa trên "các cạnh" giữa chúng.
Ví dụ:ở đây chúng tôi nhóm các mục dựa trên "độ gần" với các mục liền kề của chúng.
a = [1, 2, 3, 100, 101, 102]
# Create a new group when the difference
# between two adjacent items is > 10.
a.slice_when do |x, y|
(y - x) > 10
end
# => [[1, 2, 3], [100, 101, 102]]
Nếu bạn muốn tìm hiểu thêm, hãy xem Tài liệu Ruby cho slice_when
. Họ có một số ví dụ mã tuyệt vời.
Mảng so với Enumerables
Tôi đã sử dụng mảng trong hầu hết các ví dụ ở trên vì mảng rất dễ hiểu. Tuy nhiên, bạn nên nhớ rằng bạn có thể sử dụng slice_before
, slice_when
và slice_after
với bất kỳ liệt kê nào.
Ví dụ:nếu bạn có một tệp chứa nhiều email, bạn có thể tách các email riêng lẻ bằng cách sử dụng slice_before
. Đoạn mã dưới đây được lấy từ tài liệu.
open("mbox") { |f|
f.slice_before { |line|
line.start_with? "From "
}.each { |mail|
puts mail
}
Và hãy nhớ lưu ý rằng các phương thức lát cắt không trả về mảng. Họ trả lại bảng kê. Điều đó có nghĩa là bạn có thể sử dụng map
, each
và tất cả các phương pháp liệt kê yêu thích khác của bạn trên. Heck, bạn thậm chí có thể thực hiện một cuộc chia tách khác. :)