วันนี้เราจะมาพูดถึง slice_before
, slice_when
และ slice_after
. นี่เป็นวิธีที่มีประโยชน์มากเมื่อคุณต้องการจัดกลุ่มรายการในอาร์เรย์หรือที่นับได้อื่น ๆ ตามเกณฑ์ที่กำหนดเอง
คุณคงคุ้นเคยกับ Array#slice
. ช่วยให้คุณสามารถดึงชุดย่อยของอาร์เรย์ตามช่วงของดัชนีได้:
a = ["a", "b", "c"]
a.slice(1, 2)
# => ["b", "c"]
สิ่งนี้มีประโยชน์ แต่ไม่สามารถใช้กับตัวนับได้ เนื่องจากตัวนับไม่มีดัชนี
slice_before
, slice_when
และ slice_after
เมธอดไม่ต้องพึ่งพาดัชนี ดังนั้นคุณสามารถใช้กับดัชนีใดก็ได้ มาดูกัน!
การใช้ Enumerable#slice_before
Enumerable#slice_before
แยกและนับออกเป็นกลุ่ม ณ จุดก่อนทำการแข่งขัน
การแข่งขันจะทำผ่าน ===
โอเปอเรเตอร์ ซึ่งหมายความว่าคุณสามารถจับคู่ทุกสิ่งได้
ค่าที่ตรงกัน
คุณสามารถจับคู่ค่าเดียว ที่ควรจะเป็นที่ชัดเจน :)
a = ["a", "b", "c"]
a.slice_before("b").to_a
# => [["a"], ["b", "c"]]
การจับคู่นิพจน์ทั่วไป
คุณสามารถใช้นิพจน์ทั่วไปสำหรับการจับคู่ข้อความที่ซับซ้อนมากขึ้น
a = ["000", "b", "999"]
a.slice_before(/[a-z]/).to_a
# => [["000"], ["b", "999"]]
ช่วงที่ตรงกัน
หากคุณกำลังทำงานกับตัวเลข คุณสามารถแบ่งอาร์เรย์ตามช่วงได้
a = [100, 200, 300]
a.slice_before(150..250).to_a
# => [[100], [200, 300]]
การจับคู่คลาส
อันนี้อาจดูแปลกสำหรับคุณเล็กน้อย แต่ก็สอดคล้องกับพฤติกรรมของ ===
อย่างเต็มที่ โอเปอเรเตอร์
a = [1, "200", 1.3]
a.slice_before(String).to_a
# => [[1], ["200", 1.3]]
การใช้บล็อก
หากไม่มีตัวเลือกอื่นใดที่ยืดหยุ่นเพียงพอสำหรับให้คุณค้นหาการจับคู่โดยทางโปรแกรมด้วยการบล็อก
a = [1, 2, 3, 4, 5]
a.slice_before do |item|
item % 2 == 0
end
# => [[1], [2, 3], [4, 5]]
การใช้ Enumerable#slice_after
Enumerable#slice_after
ทำงานเหมือนกับ Enumerable#slice_before
ยกเว้นว่าสไลซ์จะเกิดขึ้นหลังการแข่งขัน ไปคิด :-)
a = ["a", "b", "c"]
a.slice_after("b").to_a
# => [["a", "b"], ["c"]]
แน่นอน คุณสามารถจับคู่โดยใช้นิพจน์ทั่วไป ช่วง และบล็อกได้ ฉันจะไม่แสดงตัวอย่างเหล่านี้ที่นี่เพราะมันจะน่าเบื่อ
ใช้ Enumerable#slice_when
Enumerable#slice_when
เป็นสัตว์ร้ายที่แตกต่างจาก slice_before
และ slice_after
. แทนที่จะจับคู่รายการเดียวในอาร์เรย์ คุณจะจับคู่รายการที่อยู่ติดกัน
ซึ่งหมายความว่าคุณสามารถจัดกลุ่มรายการตาม "ขอบ" ระหว่างรายการได้
ตัวอย่างเช่น ที่นี่เราจัดกลุ่มรายการตาม "ความใกล้เคียง" กับรายการที่อยู่ติดกัน
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]]
หากคุณสนใจที่จะเรียนรู้เพิ่มเติม โปรดดู Ruby Docs สำหรับ slice_when
. พวกเขามีตัวอย่างโค้ดที่ยอดเยี่ยมหลายประการ
อาร์เรย์เทียบกับตัวนับ
ฉันได้ใช้อาร์เรย์ในตัวอย่างส่วนใหญ่ข้างต้น เนื่องจากอาร์เรย์เข้าใจง่าย คุณควรจำไว้ว่าคุณสามารถใช้ slice_before
. ได้ , slice_when
และ slice_after
กับจำนวนใด ๆ
ตัวอย่างเช่น หากคุณมีไฟล์ที่มีอีเมลจำนวนมาก คุณสามารถแยกอีเมลแต่ละฉบับโดยใช้ slice_before
. รหัสด้านล่างนำมาจากเอกสาร
open("mbox") { |f|
f.slice_before { |line|
line.start_with? "From "
}.each { |mail|
puts mail
}
และโปรดสังเกตว่าเมธอดสไลซ์ไม่ส่งคืนอาร์เรย์ พวกเขาส่งคืนจำนวนนับ นั่นหมายความว่าคุณสามารถใช้ map
, each
และวิธีการแจกแจงอื่น ๆ ที่คุณชื่นชอบบน. เฮ็คคุณสามารถแยกได้อีก :)