Sắp xếp một mảng các đối tượng trong Ruby theo thuộc tính object?


128

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:


222

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)

81
Hoặc phiên bản tốc ký:objects.sort_by(&:attribute)
Nikola

3
các đối tượng ngắn hơn
nữa.sort_by

1
Nếu bạn gặp vấn đề với chữ hoa và chữ thường được sắp xếp riêng, bạn có thể sử dụngobjects.sort_by { |obj| obj.attribute.downcase }
campeterson

1
Bất kỳ ý tưởng làm thế nào điều này so sánh với sort!(ví dụ như tốc độ, vv)?
Joshua Pinter


35

Có, sử dụng Array#sort!điều này là dễ dàng.

myarray.sort! { |a, b|  a.attribute <=> b.attribute }

Thnx bạn thân nhưng nó không thành công với tôi, tôi có một loạt các đối tượng. Trong đó một trong các thuộc tính của đối tượng được tạo_at. Tôi muốn sắp xếp nó với lĩnh vực này. vì vậy tôi đã làm @ comm_bytes.sort! {| a, b | a.created_at <=> b.created_at} nhưng không may mắn cho tôi bạn có thể giúp .... ??

4
Có phương thức created_at để truy cập thuộc tính @created_at không? @Created_at là loại đối tượng nào? Nó có định nghĩa <=>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".
hung hăng

nó hoạt động nếu bạn thực hiện myarray = myarray.sort {...} mà không có "!"
DoruChidean

@Doru Vâng, điều đó cũng hoạt động, nhưng tại sao bạn sẽ làm điều đó? Nó ít trực tiếp và kém hiệu quả hơn. Sử dụng sortnế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ế, sortgọi sort!nội bộ, sau khi sao chép đối tượng ban đầu.
Konrad Rudolph

1
@Doru Phải có lỗi ở một nơi khác trong mã, tôi có thể đảm bảo 100% cho bạn rằng nó 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.
Konrad Rudolph

27

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

20

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] }

14

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" ]

10

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.


10

Thanh lịch hơn objects.sort_by(&:attribute), bạn có thể thêm vào .reversenếu bạn cần chuyển đổi thứ tự.



-2
@model_name.sort! { |a,b| a.attribute <=> b.attribute }

2
Có rất nhiều câu trả lời giống hệt nhau được đăng trong năm 2009. Không cần thêm câu trả lời khác.
interjay

2
Không sử dụng sortkhi 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.
Tin Man
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.