Tôi có một loạt các đối tượng trong Ruby on Rails. Tôi muốn sắp xếp mảng theo một thuộc tính của đối tượng. Có thể không?
Tôi có một loạt các đối tượng trong Ruby on Rails. Tôi muốn sắp xếp mảng theo một thuộc tính của đối tượng. Có thể không?
Câu trả lời:
Tôi khuyên bạn nên sử dụng sort_by thay thế:
objects.sort_by {|obj| obj.attribute}
Đặc biệt là nếu thuộc tính có thể được tính toán.
Hoặc một cách tiếp cận ngắn gọn hơn:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(ví dụ như tốc độ, vv)?
Có, sử dụng Array#sort!
điều này là dễ dàng.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
không? Những loại lỗi bạn đang nhận được? vân vân, vân vân, quảng cáo. Nói cách khác, chúng ta cần nhiều chi tiết hơn "nhưng không có may mắn cho tôi".
sort
nếu bạn muốn giữ nguyên bản gốc và gán kết quả cho một đối tượng khác; mặt khác, sử dụng biến thể tại chỗ , sort!
. Trong thực tế, sort
gọi sort!
nội bộ, sau khi sao chép đối tượng ban đầu.
sort!
sẽ hoạt động tốt và luôn luôn (!) Làm điều tương tự như những gì bạn đã viết.
Thứ tự tăng dần :
objects_array.sort! { |a, b| a.attribute <=> b.attribute }
hoặc là
objects_array.sort_by{ |obj| obj.attribute }
Thứ tự giảm dần :
objects_array.sort! { |a, b| b.attribute <=> a.attribute }
hoặc là
objects_array.sort_by{ |obj| obj.attribute }.reverse
trong trường hợp bạn cần sắp xếp theo hai thuộc tính, trong đó thuộc tính thứ nhất quan trọng hơn thứ hai (nghĩa là chỉ tính đến các đối số thứ hai nếu các đối số thứ nhất bằng nhau), thì bạn có thể làm như thế này
myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
hoặc trong trường hợp mảng
myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
Bạn có thể làm cho bất kỳ lớp nào có thể sắp xếp bằng cách ghi đè phương thức <=>:
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def <=>(other)
@last_name + @first_name <=> other.last_name + other.first_name
end
end
Bây giờ một mảng các đối tượng Person sẽ được sắp xếp trên last_name.
ar = [Person.new("Eric", "Cunningham"), Person.new("Homer", "Allen")]
puts ar # => [ "Eric Cunningham", "Homer Allen"] (Person objects!)
ar.sort!
puts ar # => [ "Homer Allen", "Eric Cunningham" ]
Mảng # sort hoạt động tốt, như đã đăng ở trên:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
NHƯNG, bạn cần chắc chắn rằng <=>
toán tử được triển khai cho thuộc tính đó. Nếu đó là kiểu dữ liệu gốc của Ruby, thì đây không phải là vấn đề. Mặt khác, hãy viết triển khai của riêng bạn trả về -1 nếu a <b, 0 nếu chúng bằng nhau và 1 nếu a> b.
Thanh lịch hơn objects.sort_by(&:attribute)
, bạn có thể thêm vào .reverse
nếu bạn cần chuyển đổi thứ tự.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
khi bạn sắp xếp các đối tượng không thể so sánh trực tiếp. Nếu bạn phải truy cập các thuộc tính hoặc thực hiện tính toán để lấy giá trị để so sánh sử dụng sort_by
. Nó sẽ nhanh hơn nhiều.
objects.sort_by(&:attribute)