Computer >> Máy Tính >  >> Lập trình >> Ruby

Cắt và thái hạt Ruby Enumerables

Hôm nay chúng ta sẽ nói về slice_before , slice_whenslice_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_whenslice_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_beforeslice_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_whenslice_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. :)