การจัดเรียงอาร์เรย์ใน Ruby เป็นเรื่องง่าย!
คุณ ไม่จำเป็นต้องเขียนอัลกอริธึมแฟนซี เพื่อให้ได้ผลลัพธ์ที่คุณต้องการ
แล้วต้องใช้อะไรบ้าง?
ทำความเข้าใจวิธีการจัดเรียงในตัวของ Ruby
สิ่งเหล่านี้ :
- จัดเรียง
- sort_by
- เรียงลำดับ!
วิธีการเหล่านี้ทำงานอย่างไรและทำไมจึงแตกต่างกัน
นั่นคือสิ่งที่คุณจะได้ค้นพบในบทความนี้
คุณจะได้เรียนรู้วิธีจัดเรียงอาร์เรย์ต่างๆ โดยเริ่มจาก sort
วิธีการแล้วดูที่ sort_by
สำหรับการจัดเรียงขั้นสูง (ตามค่าหลายค่า) และอื่นๆ
มาทำสิ่งนี้กันเถอะ!
เรียนรู้การใช้ Sort &Sort! วิธีการทับทิม
รูปแบบพื้นฐานที่สุดของการเรียงลำดับมีให้โดยวิธีการเรียงลำดับ Ruby ซึ่งกำหนดโดยโมดูล Enumerable
มาดูตัวอย่างกัน :
numbers = [5,3,2,1] numbers.sort # [1,2,3,5]
สังเกตว่า sort
จะส่งคืนอาร์เรย์ใหม่พร้อมผลลัพธ์
อาร์เรย์ขององค์ประกอบที่จัดเรียง!
นอกจากนี้ยังสามารถจัดเรียง "แทนที่" โดยใช้ sort!
วิธีการ
ซึ่งหมายความว่าอาร์เรย์เดิมจะ เปลี่ยน แทนที่จะสร้างใหม่ ซึ่งอาจเป็นผลดีต่อประสิทธิภาพ
การเรียงลำดับแบบกำหนดเองด้วย sort_by
ด้วย sort_by
วิธีที่คุณสามารถทำการเรียงลำดับขั้นสูงและน่าสนใจยิ่งขึ้น
คุณจะสามารถ :
- จัดเรียงตามความยาวของสตริง
- จัดเรียงตามเนื้อหาสตริง
- จัดเรียงตามว่าตัวเลขเป็นคู่หรือคี่
คุณสามารถทำได้โดยใช้ sort_by
เมธอด &บล็อกทับทิม
ตัวอย่างเช่น :
strings = %w(foo test blog a) strings.sort_by(&:length) # ["a", "foo", "test", "blog"]
วิธีนี้ทำงานอย่างไร
ก็ sort_by
method ต้องการค่าตัวเลข นั่นคือสาเหตุที่ length
ได้ผล
หากคุณเข้าใจสิ่งนี้ คุณสามารถใช้วิธีนี้ทำสิ่งดีๆ ได้ เช่น การจัดเรียงคำที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่และปล่อยให้ทุกอย่างเข้าที่
ถูกใจสิ่งนี้ :
def sort_by_capital_word(text) text .split .sort_by { |w| w[0].match?(/[A-Z]/) ? 0 : 1 } .join(" ") end sort_by_capital_word("calendar Cat tap Lamp") # "Cat Lamp calendar tap"
นอกจากนี้ยังสามารถทำการเรียงลำดับแบบกำหนดเองโดยใช้ sort
. ปกติ วิธีที่มีบล็อก
นี่คือตัวอย่าง :
strings = %w(foo test blog a) strings.sort { |a,b| a.length <=> b.length } # ["a", "foo", "test", "blog"]
หมายเหตุ :นี่
<=>
สัญลักษณ์นี้เรียกว่า "ผู้ดำเนินการยานอวกาศ" และเป็นวิธีการที่คุณสามารถนำไปใช้ในชั้นเรียนของคุณได้ ควรคืนค่า 1 (มากกว่า), 0 (เท่ากับ) หรือ -1 (น้อยกว่า)
โดยทั่วไป ฉันชอบ sort_by
เพราะเจตนาชัดเจนขึ้น อ่านง่ายกว่า และเร็วกว่านิดหน่อย
เรียงลำดับย้อนกลับ
แล้วการเรียงลำดับย้อนกลับล่ะ
คุณสามารถใช้ reverse
วิธีหลังจากการเรียงลำดับ หรือคุณสามารถใช้บล็อก &ใส่เครื่องหมายลบหน้าสิ่งที่คุณกำลังเรียงลำดับ
ให้ฉันแสดงตัวอย่างให้คุณดู :
strings = %w(foo test blog a) strings.sort_by { |str| -str.length } # ["blog", "test", "foo", "a"]
ไม่หรูหรา แต่ใช้งานได้! 🙂
การเรียงลำดับตัวอักษรและตัวเลข
สมมติว่าคุณต้องการจัดเรียงรายการสตริงที่มีตัวเลขเป็นตัวเลข
ถูกใจสิ่งนี้ :
music = %w(21.mp3 10.mp3 5.mp3 40.mp3)
โดยค่าเริ่มต้น คุณจะไม่ได้รับการจัดเรียงรายการนี้ตามที่คุณต้องการ
ตัวอย่าง :
music.sort # ["10.mp3", "21.mp3", "40.mp3", "5.mp3"]
แต่คุณสามารถแก้ไขได้โดยใช้ sort_by
:
music.sort_by { |s| s.scan(/\d+/).first.to_i } # ["5.mp3", "10.mp3", "21.mp3", "40.mp3"]
ฉันใช้นิพจน์ทั่วไป (\d+
) เพื่อให้ตรงกับตัวเลขแล้วจึงได้หมายเลขแรก (first
) &แปลงเป็นวัตถุจำนวนเต็ม (to_i
)
วิธีการจัดเรียงแฮชใน Ruby
คุณไม่ได้จำกัดแค่การเรียงลำดับอาร์เรย์ คุณยังสามารถจัดเรียงแฮชได้
ตัวอย่าง :
hash = {coconut: 200, orange: 50, bacon: 100} hash.sort_by(&:last) # [[:orange, 50], [:bacon, 100], [:coconut, 200]]
สิ่งนี้จะจัดเรียงตามค่า แต่สังเกตเห็นสิ่งที่น่าสนใจที่นี่ สิ่งที่คุณได้รับกลับไม่ใช่แฮช
คุณจะได้รับอาร์เรย์หลายมิติเมื่อจัดเรียงแฮช
หากต้องการเปลี่ยนกลับเป็นแฮช คุณสามารถใช้วิธี Array#to_h
การจัดเรียงตามค่าหลายค่า
คุณอาจต้องการจัดเรียงบางอย่างตามแอตทริบิวต์หลายรายการ หมายความว่าคุณต้องจัดเรียงตามวันที่ก่อน (เช่น) แต่เนื่องจากคุณมีหลายอย่างที่มีวันที่เดียวกัน คุณจึงมีความสัมพันธ์กัน
คุณสามารถใช้แอตทริบิวต์รองเพื่อทำลายเน็คไทได้
ตัวอย่าง :
Event = Struct.new(:name, :date) events = [] events << Event.new("book sale", Time.now) events << Event.new("course sale", Time.now) events << Event.new("new subscriber", Time.now) events << Event.new("course sale", Time.now + 1.day) events.sort_by { |event| [event.date, event.name] }
กุญแจสำคัญคืออาร์เรย์ภายใน sort_by
บล็อก
โดยที่คุณตั้งค่าแอตทริบิวต์การเรียงลำดับหลักเป็นองค์ประกอบแรกของอาร์เรย์ (event.date
) &จากนั้นแอตทริบิวต์ tie-breaker รอง (event.name
)
การใช้งาน QuickSort
เพื่อความสนุก ลองใช้วิธีการจัดเรียงของเราเอง วิธีนี้จะช้ากว่าวิธีการจัดเรียงที่มีอยู่แล้ว แต่ก็ยังเป็นแบบฝึกหัดที่น่าสนใจหากคุณชอบวิทยาการคอมพิวเตอร์
def quick_sort(list) return [] if list.empty? groups = list.group_by { |n| n <=> list.first } less_than = groups[-1] || [] first = groups[0] || [] greater_than = groups[1] || [] quick_sort(less_than) + first + quick_sort(greater_than) end p quick_sort [3, 7, 2, 1, 8, 12] # [1, 2, 3, 7, 8, 12]
แนวคิดของการเรียงลำดับอย่างรวดเร็วคือสุ่มเลือกหมายเลขหนึ่งแล้วแบ่งรายการที่เราจัดเรียงเป็นสองกลุ่ม
กลุ่มหนึ่งคือตัวเลขที่น้อยกว่าตัวเลขที่เลือก และอีกกลุ่มคือตัวเลขที่มากกว่าตัวเลขที่เลือก
จากนั้นเราก็ทำซ้ำการดำเนินการนี้จนกว่าจะจัดเรียงรายการ
เกณฑ์มาตรฐาน
เรามาดูกันว่าวิธีการจัดเรียงเหล่านี้เปรียบเทียบกันอย่างไรในแง่ของประสิทธิภาพ
ทับทิม 2.4.0 :
sort!: 1405.8 i/s sort: 1377.6 i/s - same-ish: difference falls within error sort_by reverse: 196.6 i/s - 7.15x slower sort_by: 183.7 i/s - 7.65x slower sort_by minus: 172.3 i/s - 8.16x slower sort with block: 164.1 i/s - 8.57x slower
อย่างที่คุณเห็น sort
. ปกติ วิธีการเร็วกว่า sort_by
. มาก แต่จะไม่ยืดหยุ่นเท่าเว้นแต่คุณจะใช้การบล็อก
วิดีโอ
สรุป
คุณได้เรียนรู้วิธีใช้ sort
&sort_by
วิธีการจัดเรียงอาร์เรย์และแฮชในรูปแบบต่างๆ คุณยังได้เรียนรู้เกี่ยวกับความแตกต่างด้านประสิทธิภาพและวิธีการใช้อัลกอริธึม Quicksort
นี่คือสิ่งที่คุณควรจำ :
- คุณสามารถใช้
sort
เมธอดบนอาร์เรย์ แฮช หรือออบเจกต์ที่นับได้อื่นๆ &คุณจะได้รับพฤติกรรมการเรียงลำดับเริ่มต้น (เรียงตาม<=>
โอเปอเรเตอร์) - คุณสามารถใช้
sort
ด้วยบล็อกและอาร์กิวเมนต์สองบล็อก เพื่อกำหนดว่าวัตถุหนึ่งแตกต่างจากวัตถุอื่นอย่างไร (บล็อกควรคืนค่า 1, 0 หรือ -1) - คุณสามารถใช้
sort_by
ด้วยบล็อกและหนึ่งอาร์กิวเมนต์ เพื่อกำหนดหนึ่งแอตทริบิวต์สำหรับแต่ละอ็อบเจ็กต์ซึ่งจะใช้เป็นพื้นฐานสำหรับการเรียงลำดับ (ความยาวอาร์เรย์ คุณลักษณะของอ็อบเจ็กต์ ดัชนี ฯลฯ) บล็อกควรคืนค่าจำนวนเต็มที่กำหนดตำแหน่งของวัตถุในอาร์เรย์ที่จัดเรียง
อย่าลืม แชร์โพสต์นี้ เพื่อให้ผู้คนสามารถเรียนรู้ได้มากขึ้น 🙂