Sắp xếp một mảng trong Ruby thật dễ dàng!
Bạn không cần viết bất kỳ thuật toán cầu kỳ nào để có được kết quả bạn muốn.
Vậy thì cần gì?
Hiểu các phương pháp sắp xếp tích hợp của Ruby.
Những :
- sắp xếp
- sort_by
- sắp xếp!
Các phương pháp này hoạt động như thế nào và tại sao chúng lại khác nhau?
Đó là những gì bạn sẽ khám phá trong bài viết này.
Bạn sẽ tìm hiểu các cách khác nhau để sắp xếp một mảng, bắt đầu với sort
, sau đó xem qua sort_by
để sắp xếp nâng cao (theo nhiều giá trị) và hơn thế nữa.
Hãy làm điều này!
Học cách sử dụng Sắp xếp &Sắp xếp! Phương thức Ruby
Hình thức sắp xếp cơ bản nhất được cung cấp bởi phương pháp sắp xếp Ruby, được định nghĩa bởi mô-đun Enumerable.
Hãy xem một ví dụ :
numbers = [5,3,2,1] numbers.sort # [1,2,3,5]
Lưu ý rằng sort
sẽ trả về một mảng mới với các kết quả.
Một mảng các phần tử được sắp xếp!
Cũng có thể sắp xếp “tại chỗ” bằng cách sử dụng sort!
phương pháp.
Điều này có nghĩa là mảng ban đầu sẽ thay đổi thay vì tạo một cái mới, có thể tốt cho hiệu suất.
Sắp xếp tùy chỉnh với sort_by
Với sort_by
phương pháp bạn có thể sắp xếp nâng cao và thú vị hơn.
Bạn sẽ có thể :
- Sắp xếp theo độ dài chuỗi
- Sắp xếp theo nội dung chuỗi
- Sắp xếp theo số chẵn hay lẻ
Bạn có thể thực hiện việc này với sort_by
phương thức &một khối Ruby.
Ví dụ :
strings = %w(foo test blog a) strings.sort_by(&:length) # ["a", "foo", "test", "blog"]
Điều này hoạt động như thế nào?
Chà, sort_by
phương thức yêu cầu một giá trị số, đó là lý do tại sao length
hoạt động.
Nếu bạn hiểu điều này, thì bạn có thể sử dụng phương pháp này để làm những điều thú vị, chẳng hạn như sắp xếp các từ bắt đầu bằng chữ in hoa và giữ nguyên mọi thứ khác.
Như thế này :
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"
Cũng có thể thực hiện sắp xếp tùy chỉnh bằng cách sử dụng sort
thông thường phương pháp với một khối.
Đây là một ví dụ :
strings = %w(foo test blog a) strings.sort { |a,b| a.length <=> b.length } # ["a", "foo", "test", "blog"]
Lưu ý :
<=>
này biểu tượng được gọi là “toán tử phi thuyền” và đó là một phương thức bạn có thể triển khai trong lớp của mình. Nó phải trả về 1 (lớn hơn), 0 (bằng) hoặc -1 (nhỏ hơn).
Nói chung, tôi thích sort_by
vì mục đích rõ ràng hơn, dễ đọc hơn và cũng nhanh hơn một chút.
Sắp xếp theo thứ tự ngược lại
Sắp xếp ngược lại thì sao?
Bạn có thể sử dụng reverse
sau khi sắp xếp hoặc bạn có thể sử dụng một khối &đặt dấu trừ trước thứ bạn đang phân loại.
Để tôi cho bạn xem một ví dụ :
strings = %w(foo test blog a) strings.sort_by { |str| -str.length } # ["blog", "test", "foo", "a"]
Không lạ mắt, nhưng nó hoạt động! 🙂
Sắp xếp theo kiểu chữ và số
Giả sử bạn muốn sắp xếp theo số một danh sách các chuỗi có chứa số.
Như thế này :
music = %w(21.mp3 10.mp3 5.mp3 40.mp3)
Theo mặc định, bạn sẽ không nhận được danh sách này được sắp xếp như bạn muốn.
Ví dụ :
music.sort # ["10.mp3", "21.mp3", "40.mp3", "5.mp3"]
Nhưng bạn có thể khắc phục điều này bằng cách sử dụng sort_by
:
music.sort_by { |s| s.scan(/\d+/).first.to_i } # ["5.mp3", "10.mp3", "21.mp3", "40.mp3"]
Tôi đã sử dụng một biểu thức chính quy (\d+
) để khớp các số, sau đó lấy số đầu tiên (first
) &chuyển đổi nó thành một đối tượng số nguyên (to_i
).
Cách sắp xếp hàm băm trong Ruby
Bạn không bị giới hạn trong việc sắp xếp các mảng, bạn cũng có thể sắp xếp một hàm băm.
Ví dụ :
hash = {coconut: 200, orange: 50, bacon: 100} hash.sort_by(&:last) # [[:orange, 50], [:bacon, 100], [:coconut, 200]]
Điều này sẽ sắp xếp theo giá trị, nhưng hãy lưu ý một điều thú vị ở đây, thứ bạn nhận lại không phải là một hàm băm.
Bạn nhận được một mảng nhiều chiều khi sắp xếp một hàm băm.
Để biến giá trị này trở lại thành hàm băm, bạn có thể sử dụng phương thức Mảng # to_h.
Sắp xếp theo nhiều giá trị
Bạn có thể muốn sắp xếp thứ gì đó theo nhiều thuộc tính, nghĩa là trước tiên bạn sắp xếp theo ngày (ví dụ), nhưng vì bạn có nhiều thứ có cùng ngày nên bạn gặp khó khăn.
Để phá vỡ sự ràng buộc, bạn có thể sử dụng thuộc tính phụ.
Ví dụ :
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] }
Chìa khóa ở đây là mảng bên trong sort_by
khối.
Nơi bạn đặt thuộc tính sắp xếp chính làm phần tử đầu tiên của mảng (event.date
) và sau đó là thuộc tính tie-breaker phụ (event.name
).
Triển khai QuickSort
Chỉ để giải trí, hãy triển khai phương pháp sắp xếp của riêng chúng tôi. Điều này sẽ chậm hơn so với các phương pháp sắp xếp có sẵn, nhưng đây vẫn là một bài tập thú vị nếu bạn thích khoa học máy tính.
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]
Ý tưởng của sắp xếp nhanh là chọn ngẫu nhiên một số sau đó chia danh sách chúng ta đang sắp xếp thành hai nhóm.
Một nhóm là các số nhỏ hơn số đã chọn và nhóm còn lại là các số lớn hơn số đã chọn.
Sau đó, chúng tôi chỉ cần lặp lại thao tác này cho đến khi danh sách được sắp xếp.
Điểm chuẩn
Hãy xem tất cả các phương pháp sắp xếp này so sánh với nhau về hiệu suất như thế nào.
Ruby 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
Như bạn có thể thấy, sort
thông thường phương thức nhanh hơn nhiều so với sort_by
, nhưng nó không linh hoạt trừ khi bạn sử dụng một khối.
Video
Tóm tắt
Bạn đã học cách sử dụng sort
&sort_by
các phương pháp để sắp xếp các mảng và hàm băm của bạn theo những cách khác nhau. Bạn cũng đã tìm hiểu về sự khác biệt về hiệu suất và cách triển khai thuật toán nhanh chóng.
Đây là những gì bạn nên nhớ :
- Bạn có thể sử dụng
sort
phương thức trên một mảng, hàm băm hoặc một đối tượng Có thể đếm được khác &bạn sẽ nhận được hành vi sắp xếp mặc định (sắp xếp dựa trên<=>
toán tử) - Bạn có thể sử dụng
sort
với một khối và hai đối số khối, để xác định một đối tượng khác với đối tượng khác như thế nào (khối phải trả về 1, 0 hoặc -1) - Bạn có thể sử dụng
sort_by
với một khối và một đối số, để xác định một thuộc tính cho mỗi đối tượng sẽ được sử dụng làm cơ sở để sắp xếp (độ dài mảng, thuộc tính đối tượng, chỉ mục, v.v.). Khối phải trả về một giá trị số nguyên xác định vị trí của đối tượng trong mảng đã sắp xếp.
Đừng quên chia sẻ bài đăng này để nhiều người có thể học hỏi. 🙂